initial: project scaffold with agent-ops, cli, client, services, packages
This commit is contained in:
commit
5c79ca171e
220 changed files with 10678 additions and 0 deletions
2
.aiexclude
Normal file
2
.aiexclude
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
agent-task/archive/**
|
||||
agent-ops/roadmap/archive/**
|
||||
9
.claude/settings.json
Normal file
9
.claude/settings.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||
"permissions": {
|
||||
"deny": [
|
||||
"Read(./agent-task/archive/**)",
|
||||
"Read(./agent-ops/roadmap/archive/**)"
|
||||
]
|
||||
}
|
||||
}
|
||||
2
.clineignore
Normal file
2
.clineignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
agent-task/archive/**
|
||||
agent-ops/roadmap/archive/**
|
||||
28
.clinerules
Normal file
28
.clinerules
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 공통 규칙
|
||||
|
||||
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
1. `agent-ops/rules/project/rules.md`
|
||||
2. `agent-ops/rules/private/rules.md`
|
||||
3. `agent-ops/roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||
|
||||
# 스킬 규칙
|
||||
|
||||
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- README 생성
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- 현재 작업 지점 / 남은 작업 분석
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
- agent-ops 업데이트 / 진입 파일 재적용
|
||||
2
.cursorignore
Normal file
2
.cursorignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
agent-task/archive/**
|
||||
agent-ops/roadmap/archive/**
|
||||
28
.cursorrules
Normal file
28
.cursorrules
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 공통 규칙
|
||||
|
||||
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
1. `agent-ops/rules/project/rules.md`
|
||||
2. `agent-ops/rules/private/rules.md`
|
||||
3. `agent-ops/roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||
|
||||
# 스킬 규칙
|
||||
|
||||
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- README 생성
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- 현재 작업 지점 / 남은 작업 분석
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
- agent-ops 업데이트 / 진입 파일 재적용
|
||||
2
.geminiignore
Normal file
2
.geminiignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
agent-task/archive/**
|
||||
agent-ops/roadmap/archive/**
|
||||
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
.DS_Store
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
*.log
|
||||
|
||||
.tmp/
|
||||
.build/
|
||||
coverage/
|
||||
|
||||
# Go
|
||||
bin/*.exe
|
||||
*.test
|
||||
|
||||
# Dart / Flutter
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
build/
|
||||
|
||||
# Local IDE state
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Agent-Ops Private Rules
|
||||
agent-ops/rules/private/
|
||||
28
AGENTS.md
Normal file
28
AGENTS.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 공통 규칙
|
||||
|
||||
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
1. `agent-ops/rules/project/rules.md`
|
||||
2. `agent-ops/rules/private/rules.md`
|
||||
3. `agent-ops/roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||
|
||||
# 스킬 규칙
|
||||
|
||||
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- README 생성
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- 현재 작업 지점 / 남은 작업 분석
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
- agent-ops 업데이트 / 진입 파일 재적용
|
||||
28
CLAUDE.md
Normal file
28
CLAUDE.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 공통 규칙
|
||||
|
||||
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
1. `agent-ops/rules/project/rules.md`
|
||||
2. `agent-ops/rules/private/rules.md`
|
||||
3. `agent-ops/roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||
|
||||
# 스킬 규칙
|
||||
|
||||
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- README 생성
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- 현재 작업 지점 / 남은 작업 분석
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
- agent-ops 업데이트 / 진입 파일 재적용
|
||||
28
GEMINI.md
Normal file
28
GEMINI.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 공통 규칙
|
||||
|
||||
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
1. `agent-ops/rules/project/rules.md`
|
||||
2. `agent-ops/rules/private/rules.md`
|
||||
3. `agent-ops/roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||
|
||||
# 스킬 규칙
|
||||
|
||||
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- README 생성
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- 현재 작업 지점 / 남은 작업 분석
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
- agent-ops 업데이트 / 진입 파일 재적용
|
||||
121
README.md
Normal file
121
README.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# ALT
|
||||
|
||||
ALT는 개인용 quant system workspace다. 한국장 일봉 기반 MVP에서 시작해, 장기적으로 미국장, 백테스트, 데이터 정규화, 페이퍼 트레이딩, 포트폴리오/리스크 관리, Flutter 클라이언트까지 확장할 수 있는 운영형 구조를 목표로 한다.
|
||||
|
||||
Go 서비스와 도구는 루트 `go.work`로 묶고, Flutter가 web/mobile/desktop 클라이언트 표면을 담당한다. 실시간 통신은 sibling workspace의 `../proto-socket/go`를 transport로 사용하며, ALT 애플리케이션 계약은 `packages/contracts/proto`의 protobuf schema를 원천으로 둔다.
|
||||
|
||||
## 현재 상태
|
||||
|
||||
현재 저장소는 초기 scaffold 단계다.
|
||||
|
||||
- `services/api`는 proto-socket WebSocket endpoint scaffold를 제공한다.
|
||||
- `services/worker`는 데이터 수집, 정규화, 백테스트, scheduled job을 위한 worker surface다.
|
||||
- `apps/client`는 Riverpod과 `go_router`를 사용하는 Flutter client shell이다.
|
||||
- `packages/contracts`에는 `alt.v1` protobuf 계약 초안이 있다.
|
||||
- `packages/domain`에는 market/backtest vocabulary와 value object skeleton이 있다.
|
||||
- PostgreSQL 17과 Redis 7 local stack은 `deployments/local/docker-compose.yml`에 있다.
|
||||
- 로드맵 진입점은 `agent-ops/roadmap/current.md`다. 일반 작업에서는 전체 `ROADMAP.md`를 매번 읽지 않고, 활성 Milestone 문서를 선택해 읽는다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```bash
|
||||
# 사용 가능한 entrypoint 확인
|
||||
bin/dev
|
||||
|
||||
# 로컬 PostgreSQL/Redis 실행
|
||||
docker compose -f deployments/local/docker-compose.yml up -d
|
||||
|
||||
# API socket server 실행
|
||||
cd services/api
|
||||
go run ./cmd/alt-api
|
||||
```
|
||||
|
||||
Flutter client는 별도 터미널에서 실행한다.
|
||||
|
||||
```bash
|
||||
cd apps/client
|
||||
flutter run -d chrome
|
||||
```
|
||||
|
||||
전체 검증은 루트에서 실행한다.
|
||||
|
||||
```bash
|
||||
bin/test
|
||||
bin/lint
|
||||
bin/build
|
||||
```
|
||||
|
||||
## 주요 명령
|
||||
|
||||
| 목적 | 명령 | 비고 |
|
||||
|------|------|------|
|
||||
| 개발 entrypoint 확인 | `bin/dev` | infra, API, worker, CLI, client 실행 명령을 출력한다. |
|
||||
| 전체 테스트 | `bin/test` | Go module test와 Flutter test를 실행한다. |
|
||||
| 전체 lint/analyze | `bin/lint` | Go `vet`와 Flutter analyze를 실행한다. |
|
||||
| 전체 build | `bin/build` | Go binary와 Flutter web build를 생성한다. |
|
||||
| 로컬 infra 실행 | `docker compose -f deployments/local/docker-compose.yml up -d` | PostgreSQL과 Redis를 실행한다. |
|
||||
| API 실행 | `cd services/api && go run ./cmd/alt-api` | 기본 socket path는 `/socket`이다. |
|
||||
| Worker 실행 | `cd services/worker && go run ./cmd/alt-worker` | 현재는 worker scaffold 상태다. |
|
||||
| CLI 실행 | `cd apps/cli && go run ./cmd/alt` | 운영자 CLI scaffold다. |
|
||||
| Client 실행 | `cd apps/client && flutter run -d chrome` | Flutter web target 기준 개발 실행이다. |
|
||||
|
||||
## 구조
|
||||
|
||||
| 경로 | 역할 |
|
||||
|------|------|
|
||||
| `services/api/` | 클라이언트-facing proto-socket API endpoint. |
|
||||
| `services/worker/` | import, normalization, backtest, scheduled job worker surface. |
|
||||
| `apps/cli/` | 로컬/운영자 작업용 Go CLI. |
|
||||
| `apps/client/` | Flutter client for web/mobile/desktop. |
|
||||
| `packages/contracts/` | ALT protobuf contracts and compatibility notes. |
|
||||
| `packages/domain/` | market/backtest shared Go domain model. |
|
||||
| `deployments/local/` | local PostgreSQL and Redis development environment. |
|
||||
| `bin/` | workspace-level helper entrypoints. |
|
||||
| `agent-ops/` | AI agent rules, domain rules, common skills, roadmap templates. |
|
||||
|
||||
## 작업 맥락
|
||||
|
||||
AI agent는 작업 전에 루트 지침과 관련 domain rule을 먼저 확인한다.
|
||||
|
||||
- `AGENTS.md`
|
||||
- `agent-ops/rules/project/rules.md`
|
||||
- `agent-ops/rules/project/domain/*/rules.md`
|
||||
- README 작업은 `agent-ops/skills/common/create-readme/SKILL.md`를 따른다.
|
||||
- 로드맵 작업은 `agent-ops/roadmap/current.md`와 활성 milestone 문서를 기준으로 한다.
|
||||
|
||||
중요한 경계는 다음과 같다.
|
||||
|
||||
- `proto-socket`은 transport layer다. ALT application message는 `packages/contracts/proto`에 둔다.
|
||||
- `packages/domain`은 transport나 persistence detail에 의존하지 않는다.
|
||||
- `services/api`는 socket/session boundary를 담당한다.
|
||||
- `services/worker`는 오래 걸리거나 비동기적인 데이터/백테스트 작업을 담당한다.
|
||||
- `apps/client`는 Flutter feature-first 구조를 사용한다.
|
||||
|
||||
## 개발 흐름
|
||||
|
||||
- 전체 workspace 검증은 가능한 한 루트 `bin/test`, `bin/lint`, `bin/build`를 우선 사용한다.
|
||||
- API, worker, client, contracts가 함께 움직이는 변경은 같은 작업 흐름에서 닫는다.
|
||||
- protobuf generated output은 source schema에서 생성하고 손으로 편집하지 않는다.
|
||||
- 새 Go module을 추가하면 `go.work`에 등록한다.
|
||||
- 로컬 secret이나 개인 설정 파일은 커밋하지 않는다.
|
||||
|
||||
## 환경 변수
|
||||
|
||||
| 이름 | 설명 | 필수 |
|
||||
|------|------|------|
|
||||
| `ALT_API_HOST` | API socket server host. 기본값 `127.0.0.1`. | 아니오 |
|
||||
| `ALT_API_PORT` | API socket server port. 기본값 `8080`. | 아니오 |
|
||||
| `ALT_API_SOCKET_PATH` | API WebSocket path. 기본값 `/socket`. | 아니오 |
|
||||
| `ALT_SOCKET_HEARTBEAT_INTERVAL_SEC` | proto-socket heartbeat interval. 기본값 `30`. | 아니오 |
|
||||
| `ALT_SOCKET_HEARTBEAT_WAIT_SEC` | proto-socket heartbeat wait. 기본값 `10`. | 아니오 |
|
||||
| `DATABASE_URL` | worker에서 사용할 PostgreSQL URL. local fallback 있음. | 아니오 |
|
||||
| `REDIS_URL` | worker에서 사용할 Redis URL. local fallback 있음. | 아니오 |
|
||||
|
||||
## 참고 문서
|
||||
|
||||
- `apps/client/README.md`
|
||||
- `packages/contracts/README.md`
|
||||
- `agent-ops/rules/project/rules.md`
|
||||
- `agent-ops/roadmap/current.md`
|
||||
- `agent-ops/skills/common/create-roadmap/SKILL.md`
|
||||
- `agent-ops/skills/common/update-roadmap/SKILL.md`
|
||||
1
agent-ops/.version
Normal file
1
agent-ops/.version
Normal file
|
|
@ -0,0 +1 @@
|
|||
1.1.49
|
||||
188
agent-ops/bin/ai-ignore.sh
Executable file
188
agent-ops/bin/ai-ignore.sh
Executable file
|
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Shared AI ignore / permission defaults for init and sync flows.
|
||||
AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN="agent-task/archive/**"
|
||||
AGENT_OPS_ROADMAP_ARCHIVE_IGNORE_PATTERN="agent-ops/roadmap/archive/**"
|
||||
AGENT_OPS_AI_IGNORE_FILES=(".geminiignore" ".aiexclude" ".cursorignore" ".clineignore")
|
||||
AGENT_OPS_AI_PERMISSION_FILES=(".claude/settings.json" "opencode.json")
|
||||
AGENT_OPS_AI_SYNC_FILES=("${AGENT_OPS_AI_IGNORE_FILES[@]}" "${AGENT_OPS_AI_PERMISSION_FILES[@]}")
|
||||
|
||||
agent_ops_append_unique_line() {
|
||||
local file="$1"
|
||||
local line="$2"
|
||||
|
||||
touch "$file"
|
||||
if ! grep -qxF "$line" "$file"; then
|
||||
printf "%s\n" "$line" >> "$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)
|
||||
| append_unique("Read(./agent-task/archive/**)")
|
||||
| append_unique("Read(./agent-ops/roadmap/archive/**)")
|
||||
)
|
||||
'
|
||||
|
||||
agent_ops_merge_json_with_jq \
|
||||
"$file" \
|
||||
"$filter" \
|
||||
"Note: .claude/settings.json exists; add Read(./agent-task/archive/**) and Read(./agent-ops/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)
|
||||
| index("Read(./agent-task/archive/**)") and index("Read(./agent-ops/roadmap/archive/**)")
|
||||
'
|
||||
|
||||
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-ops/roadmap/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"
|
||||
| .permission.read["agent-ops/roadmap/archive/**"] = "deny"
|
||||
| .permission.glob = ((.permission.glob // {}) | as_object)
|
||||
| .permission.glob["agent-task/archive/**"] = "deny"
|
||||
| .permission.glob["agent-ops/roadmap/archive/**"] = "deny"
|
||||
| .watcher = ((.watcher // {}) | as_object)
|
||||
| .watcher.ignore = (
|
||||
(.watcher.ignore | as_array)
|
||||
| append_unique("agent-task/archive/**")
|
||||
| append_unique("agent-ops/roadmap/archive/**")
|
||||
)
|
||||
'
|
||||
|
||||
agent_ops_merge_json_with_jq \
|
||||
"$file" \
|
||||
"$filter" \
|
||||
"Note: opencode.json exists; add agent-task/archive/** and agent-ops/roadmap/archive/** read/glob deny and 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.read["agent-ops/roadmap/archive/**"] == "deny")
|
||||
and (.permission.glob["agent-task/archive/**"] == "deny")
|
||||
and (.permission.glob["agent-ops/roadmap/archive/**"] == "deny")
|
||||
and ((.watcher.ignore | as_array) | index("agent-task/archive/**") and index("agent-ops/roadmap/archive/**"))
|
||||
'
|
||||
|
||||
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-ops/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
|
||||
|
||||
for ignore_file in "${AGENT_OPS_AI_IGNORE_FILES[@]}"; do
|
||||
agent_ops_append_unique_line "$target_dir/$ignore_file" "$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN"
|
||||
agent_ops_append_unique_line "$target_dir/$ignore_file" "$AGENT_OPS_ROADMAP_ARCHIVE_IGNORE_PATTERN"
|
||||
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/**)",
|
||||
"Read(./agent-ops/roadmap/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",
|
||||
"agent-ops/roadmap/archive/**": "deny"
|
||||
},
|
||||
"glob": {
|
||||
"agent-task/archive/**": "deny",
|
||||
"agent-ops/roadmap/archive/**": "deny"
|
||||
}
|
||||
},
|
||||
"watcher": {
|
||||
"ignore": [
|
||||
"agent-task/archive/**",
|
||||
"agent-ops/roadmap/archive/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
elif ! agent_ops_opencode_config_complete "$target_dir/opencode.json"; then
|
||||
agent_ops_merge_opencode_config "$target_dir/opencode.json"
|
||||
fi
|
||||
}
|
||||
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
|
||||
}
|
||||
86
agent-ops/bin/init-agent-ops.sh
Executable file
86
agent-ops/bin/init-agent-ops.sh
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
#!/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"
|
||||
}
|
||||
|
||||
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"
|
||||
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
|
||||
|
||||
echo "Successfully initialized agent-ops in $TARGET_DIR"
|
||||
echo "Note: agent-ops/rules/project and agent-ops/skills/project are initialized as empty."
|
||||
331
agent-ops/bin/sync.sh
Executable file
331
agent-ops/bin/sync.sh
Executable file
|
|
@ -0,0 +1,331 @@
|
|||
#!/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 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(agentic-framework) → 현재 프로젝트 로 pull"
|
||||
echo ""
|
||||
echo " target: 폴더명 (동일 레벨 탐색) | 상대경로 | 절대경로"
|
||||
echo " agentic-framework에서 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 모드: agentic-framework → 현재 프로젝트 ─────────────────────────────
|
||||
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: agentic-framework에서는 --pull을 사용할 수 없습니다.${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$TARGET/.agent-ops-source" ]]; then
|
||||
echo -e "${RED}Error: target이 agentic-framework가 아닙니다 (.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 | framework 버전: $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
|
||||
|
||||
# ── agentic-framework에서 다른 프로젝트로 ────────────────────────────────────
|
||||
if [[ "$IS_FRAMEWORK" == "1" ]]; then
|
||||
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
|
||||
|
||||
# ── 일반 프로젝트에서 agentic-framework로 (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이 agentic-framework가 아닙니다 (.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 | framework 버전: $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}⚠ 버전 충돌: framework($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}"
|
||||
63
agent-ops/roadmap/ROADMAP.md
Normal file
63
agent-ops/roadmap/ROADMAP.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# 로드맵
|
||||
|
||||
## 전체 목표
|
||||
|
||||
ALT는 개인용 quant system workspace로, 한국장 일봉 MVP에서 시작해 시장 데이터 수집, 정규화, 백테스트, 결과 분석, Flutter 운영 클라이언트, 페이퍼 트레이딩, 미국장 확장, 실거래 경계까지 단계적으로 확장한다. Go 서비스는 뒤집지 않는 운영 코어를 담당하고, Flutter client는 web/mobile/desktop 단일 UI 표면을 담당하며, proto-socket과 ALT protobuf contracts가 런타임 사이의 통신 기준이 된다.
|
||||
|
||||
## Phase 흐름
|
||||
|
||||
- 기반 정렬: agent-first monorepo, Go workspace, contracts, proto-socket session loop, PostgreSQL/Redis worker backbone을 안정화한다.
|
||||
- 데이터 기반: 한국장 일봉을 대상으로 provider-neutral market data import, normalization, persistence를 만든다.
|
||||
- 백테스트 루프: 일봉 기반 strategy execution, backtest lifecycle, result persistence, repeatable verification을 만든다.
|
||||
- 운영 표면: Flutter client에서 백테스트와 market data 상태를 조회하고 실행할 수 있는 operator console을 만든다.
|
||||
- 거래 확장: paper trading, 미국장 확장, 주문/리스크/포트폴리오, 실거래 adapter 경계를 MVP 이후 단계로 연다.
|
||||
|
||||
## Milestone 목록
|
||||
|
||||
### 기반 정렬
|
||||
|
||||
- [Workspace Baseline](milestones/workspace-baseline.md) - 상태: 완료; 목표: agent-ops와 scaffold가 있는 AI-first monorepo 기준선을 마련한다.
|
||||
- [Contract and Codegen Baseline](milestones/contract-codegen-baseline.md) - 상태: 계획; 목표: ALT application protobuf 계약과 Go/Dart 생성 흐름을 반복 가능하게 만든다.
|
||||
- [Socket Session Loop](milestones/socket-session-loop.md) - 상태: 계획; 목표: proto-socket 기반 API와 Flutter client 사이의 최소 handshake/request-response loop를 닫는다.
|
||||
- [Persistence and Worker Backbone](milestones/persistence-worker-backbone.md) - 상태: 계획; 목표: PostgreSQL/Redis 기반의 durable storage와 비동기 worker 실행 기준을 마련한다.
|
||||
|
||||
### 데이터 기반
|
||||
|
||||
- [Korea Daily Data Foundation](milestones/korea-daily-data-foundation.md) - 상태: 계획; 목표: 한국장 일봉 데이터를 provider-neutral 모델로 수집, 정규화, 저장하는 첫 파이프라인을 만든다.
|
||||
|
||||
### 백테스트 루프
|
||||
|
||||
- [Backtest Engine Baseline](milestones/backtest-engine-baseline.md) - 상태: 계획; 목표: 일봉 데이터를 기준으로 재현 가능한 backtest execution loop와 결과 저장을 만든다.
|
||||
- [Backtest Analysis Surface](milestones/backtest-analysis-surface.md) - 상태: 계획; 목표: backtest 결과를 operator가 비교하고 해석할 수 있는 기본 분석 표면을 만든다.
|
||||
|
||||
### 운영 표면
|
||||
|
||||
- [Flutter Operator Console](milestones/flutter-operator-console.md) - 상태: 계획; 목표: Flutter client에서 market data, backtest run, result를 조회하고 실행 요청할 수 있는 운영 화면을 만든다.
|
||||
|
||||
### 거래 확장
|
||||
|
||||
- [Paper Trading Readiness](milestones/paper-trading-readiness.md) - 상태: 계획; 목표: 실거래 전에 전략 실행, 가상 주문, 포지션, 리스크 흐름을 paper trading 경계로 검증한다.
|
||||
- [US Market Expansion](milestones/us-market-expansion.md) - 상태: 계획; 목표: 한국장 MVP 구조 위에 미국장 데이터를 추가한다.
|
||||
- [Live Trading Boundary](milestones/live-trading-boundary.md) - 상태: 보류; 목표: 실거래 adapter, 주문, 리스크, 포트폴리오 경계를 paper trading 안정화 이후에 연다.
|
||||
|
||||
## 아카이브 Milestone 요약
|
||||
|
||||
- 없음
|
||||
|
||||
## 로딩 정책
|
||||
|
||||
- 일반 작업에서는 `agent-ops/roadmap/ROADMAP.md`를 매번 읽지 않는다.
|
||||
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-ops/roadmap/current.md`를 먼저 읽는다.
|
||||
- `current.md`는 현재 작업 위치가 아니라 활성 Milestone 후보 목록이다.
|
||||
- `current.md`에는 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- `current.md`의 활성 Milestone은 `agent-ops/roadmap/milestones/` 하위 문서만 가리키며, `agent-ops/roadmap/archive/**`는 포함하지 않는다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 활성 Milestone 문서를 같은 세션에서 1회 읽는다.
|
||||
- 활성 Milestone 밖의 작업이면 이 문서의 Milestone 목록을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||
- 이 문서는 로드맵 생성/갱신, Phase 전환, Milestone 추가/수정 요청이 있을 때만 읽는다.
|
||||
- 상세 작업과 완료 기준은 각 Milestone 문서의 체크리스트로 관리한다.
|
||||
- 완료 또는 폐기되어 아카이브된 Milestone은 이 문서의 `아카이브 Milestone 요약`에 당시 요약만 남기고, 아카이브 문서 링크나 상세 경로는 남기지 않는다.
|
||||
- 상세 문서가 있는 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
- 아카이브된 Milestone 문서는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획 생성, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
|
||||
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조/도메인 rule/플랫폼 관례로 정할 수 있는 작업은 표준선으로 기록하고 진행할 수 있다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
16
agent-ops/roadmap/current.md
Normal file
16
agent-ops/roadmap/current.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# 현재 로드맵 컨텍스트
|
||||
|
||||
## 활성 Milestone
|
||||
|
||||
- Contract and Codegen Baseline: agent-ops/roadmap/milestones/contract-codegen-baseline.md
|
||||
- Socket Session Loop: agent-ops/roadmap/milestones/socket-session-loop.md
|
||||
- Persistence and Worker Backbone: agent-ops/roadmap/milestones/persistence-worker-backbone.md
|
||||
|
||||
## 선택 규칙
|
||||
|
||||
- 이 문서는 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- 활성 Milestone은 `agent-ops/roadmap/milestones/` 하위 문서만 가리키며, `agent-ops/roadmap/archive/**`는 포함하지 않는다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 Milestone을 선택하고 같은 세션에서 1회 읽는다.
|
||||
- 활성 Milestone 둘 이상에 걸치면 필요한 Milestone 문서를 모두 읽고 작업 범위를 좁힌다.
|
||||
- 활성 Milestone 밖의 작업이면 `agent-ops/roadmap/ROADMAP.md`의 Milestone 목록을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 구현이나 구현 계획을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다. 관련 결정이 없고 표준선으로 처리 가능하면 잠금을 유지한 채 진행할 수 있으며, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
55
agent-ops/roadmap/milestones/backtest-analysis-surface.md
Normal file
55
agent-ops/roadmap/milestones/backtest-analysis-surface.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Backtest Analysis Surface
|
||||
|
||||
## 목표
|
||||
|
||||
backtest 결과를 단순 성공/실패가 아니라 operator가 비교하고 해석할 수 있는 기본 분석 표면으로 확장한다. MVP에서는 핵심 summary와 run comparison을 우선한다.
|
||||
|
||||
## 단계
|
||||
|
||||
백테스트 루프
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- backtest result summary 확장
|
||||
- equity curve 또는 time-series result 저장 기준
|
||||
- run list/detail query
|
||||
- 기본 comparison capability
|
||||
- client 표시를 위한 contract shape
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [summary-metrics] ending equity 외 최소 summary metrics가 있다.
|
||||
- [ ] [equity-curve] run별 equity curve 또는 동등한 time-series result를 저장/조회한다.
|
||||
- [ ] [run-list] backtest run 목록과 상태를 조회할 수 있다.
|
||||
- [ ] [run-detail] 단일 run의 spec, status, result를 조회할 수 있다.
|
||||
- [ ] [compare-runs] 둘 이상의 run을 비교할 기본 기준이 있다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] Flutter client가 표시할 수 있는 result contract가 존재한다.
|
||||
- [ ] worker/API/client 경계가 backtest result를 일관되게 다룬다.
|
||||
- [ ] fixture 기반 result 조회 테스트가 통과한다.
|
||||
- [ ] `bin/test`와 `bin/lint`가 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 전문 리포트 생성
|
||||
- 고급 통계/리스크 지표 전체
|
||||
- 외부 포트폴리오 시스템 연동
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/worker/`, `services/api/`, `apps/client/`, `packages/contracts/`
|
||||
- 표준선(선택): MVP 분석은 operator가 다음 백테스트 판단을 할 수 있는 최소 지표에 집중한다.
|
||||
- 선행 작업: Backtest Engine Baseline
|
||||
- 후속 작업: Flutter Operator Console
|
||||
- 확인 필요: 없음
|
||||
56
agent-ops/roadmap/milestones/backtest-engine-baseline.md
Normal file
56
agent-ops/roadmap/milestones/backtest-engine-baseline.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Backtest Engine Baseline
|
||||
|
||||
## 목표
|
||||
|
||||
정규화된 일봉 데이터를 사용해 전략 실행, portfolio state, result summary가 재현 가능한 backtest loop를 만든다. 이 milestone은 백테스트 기반을 ALT 확장의 중심축으로 고정한다.
|
||||
|
||||
## 단계
|
||||
|
||||
백테스트 루프
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- daily bar 기반 strategy execution skeleton
|
||||
- deterministic backtest run lifecycle
|
||||
- starting cash, ending equity, trades/positions summary
|
||||
- result persistence and query
|
||||
- fixture data 기반 검증
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [run-lifecycle] backtest run의 pending/running/succeeded/failed/canceled lifecycle이 있다.
|
||||
- [ ] [strategy-port] strategy를 engine에 주입할 port 또는 interface가 있다.
|
||||
- [ ] [portfolio-state] cash, position, equity를 계산하는 최소 portfolio state가 있다.
|
||||
- [ ] [result-store] backtest result가 저장되고 조회된다.
|
||||
- [ ] [fixture-test] fixture daily bars로 deterministic test가 통과한다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] 동일한 fixture와 strategy 입력으로 동일한 result가 나온다.
|
||||
- [ ] worker가 backtest 실행을 소유하고 API는 실행 요청/조회 경계만 담당한다.
|
||||
- [ ] 결과가 contracts/client에서 조회 가능한 형태로 연결될 수 있다.
|
||||
- [ ] `bin/test`와 `bin/lint`가 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 실시간 전략 실행
|
||||
- paper/live order routing
|
||||
- 고급 리스크 모델
|
||||
- 고급 성과 분석 지표 전체
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `packages/domain/backtest/`, `services/worker/`, `packages/contracts/proto/alt/v1/backtest.proto`
|
||||
- 표준선(선택): Go는 Hexagonal Architecture, light CQRS, domain event 표현을 기본 설계 프레임으로 삼는다.
|
||||
- 선행 작업: Korea Daily Data Foundation
|
||||
- 후속 작업: Backtest Analysis Surface
|
||||
- 확인 필요: 없음
|
||||
57
agent-ops/roadmap/milestones/contract-codegen-baseline.md
Normal file
57
agent-ops/roadmap/milestones/contract-codegen-baseline.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Contract and Codegen Baseline
|
||||
|
||||
## 목표
|
||||
|
||||
proto-socket을 transport로 유지하면서 ALT application protobuf 계약을 Go API/worker와 Flutter client가 반복 가능하게 소비할 수 있는 기준을 만든다. 계약은 `alt.v1`을 유지하고, generated output은 source schema에서만 생성한다.
|
||||
|
||||
## 단계
|
||||
|
||||
기반 정렬
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- `packages/contracts/proto/alt/v1` schema 정리
|
||||
- Go/Dart protobuf generation 명령과 산출 위치 결정
|
||||
- proto-socket parser map과 typeName 등록 기준
|
||||
- contract compatibility note
|
||||
- generated output 검증 명령
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [schema-baseline] `common.proto`, `market.proto`, `backtest.proto`가 MVP payload 기준을 담는다.
|
||||
- [ ] [go-codegen] Go generated contract를 반복 생성할 수 있는 명령이 있다.
|
||||
- [ ] [dart-codegen] Flutter client가 사용할 Dart generated contract를 반복 생성할 수 있는 명령이 있다.
|
||||
- [ ] [parser-map] API/client에서 contract message parser map을 구성할 표준 위치와 패턴이 정해져 있다.
|
||||
- [ ] [compat-note] additive change, field number, versioning 기준이 contracts 문서에 정리되어 있다.
|
||||
- [ ] [contract-check] root 검증 또는 contracts 검증 명령이 schema/codegen drift를 감지한다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] Go와 Dart contract generation 명령이 문서화되어 있고 로컬에서 실행된다.
|
||||
- [ ] generated output은 source schema와 함께 검증할 수 있다.
|
||||
- [ ] proto-socket transport proto와 ALT application proto의 책임이 문서에서 분리되어 있다.
|
||||
- [ ] `bin/test`와 `bin/lint`가 contract 변경 후 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 실제 KIS 데이터 수집 구현
|
||||
- DB persistence schema 확정
|
||||
- Flutter 전체 화면 구현
|
||||
- 실거래 주문 계약
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `packages/contracts/`, `services/api/`, `apps/client/`
|
||||
- 표준선(선택): proto-socket은 transport layer이고 ALT payload는 `packages/contracts/proto`가 source-of-truth다.
|
||||
- 선행 작업: Workspace Baseline
|
||||
- 후속 작업: Socket Session Loop
|
||||
- 확인 필요: 없음
|
||||
58
agent-ops/roadmap/milestones/flutter-operator-console.md
Normal file
58
agent-ops/roadmap/milestones/flutter-operator-console.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Flutter Operator Console
|
||||
|
||||
## 목표
|
||||
|
||||
Flutter client를 ALT의 공식 UI client로 삼아 market data 상태, backtest run, result를 조회하고 실행 요청할 수 있는 operator console을 만든다. 별도 TypeScript web app은 기본 경로로 두지 않는다.
|
||||
|
||||
## 단계
|
||||
|
||||
운영 표면
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- Flutter feature-first 화면 구조
|
||||
- socket connection state
|
||||
- backtest run list/detail
|
||||
- start backtest request form
|
||||
- market data import/status view
|
||||
- responsive web/mobile/desktop navigation
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [connect-state] client가 API socket 연결 상태를 표시한다.
|
||||
- [ ] [backtest-list] backtest run 목록을 조회하고 표시한다.
|
||||
- [ ] [backtest-detail] backtest run detail과 result를 표시한다.
|
||||
- [ ] [start-run] operator가 backtest 실행을 요청할 수 있다.
|
||||
- [ ] [market-status] market data import/status를 조회할 수 있다.
|
||||
- [ ] [responsive-nav] web/mobile/desktop target에서 기본 navigation이 작동한다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] Flutter test가 주요 화면 shell과 상태 표시를 검증한다.
|
||||
- [ ] client는 generated/mapped contracts를 통해 API와 통신한다.
|
||||
- [ ] presentation widget에 production endpoint 가정이 hard-code되지 않는다.
|
||||
- [ ] `bin/test`, `bin/lint`, `bin/build`가 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 별도 TypeScript web app
|
||||
- 고급 charting 전체
|
||||
- push notification
|
||||
- mobile app store 배포 설정
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `apps/client/`, `packages/contracts/`, `services/api/`
|
||||
- 표준선(선택): Flutter는 feature-first Clean Architecture와 Riverpod을 기본 설계 프레임으로 삼는다.
|
||||
- 선행 작업: Socket Session Loop, Backtest Analysis Surface
|
||||
- 후속 작업: Paper Trading Readiness
|
||||
- 확인 필요: 없음
|
||||
60
agent-ops/roadmap/milestones/korea-daily-data-foundation.md
Normal file
60
agent-ops/roadmap/milestones/korea-daily-data-foundation.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Korea Daily Data Foundation
|
||||
|
||||
## 목표
|
||||
|
||||
한국장 일봉 데이터를 첫 MVP market data로 삼아 provider-neutral import, normalization, persistence 파이프라인을 만든다. 한투/KIS는 초기 provider 후보로 보되, domain model은 한국장에만 종속되지 않게 유지한다.
|
||||
|
||||
## 단계
|
||||
|
||||
데이터 기반
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 잠금
|
||||
- 결정 필요: 아래 체크리스트
|
||||
- [ ] MVP에서 우선 수집할 한국장 universe를 watchlist, KOSPI/KOSDAQ 전체, 또는 특정 섹터 중 무엇으로 둘지 결정한다.
|
||||
- [ ] KIS credential과 계정 환경을 local secret/env 기준으로 어떻게 제공할지 결정한다.
|
||||
|
||||
## 범위
|
||||
|
||||
- KRX/Korea daily bar import pipeline
|
||||
- provider symbol mapping
|
||||
- normalized instrument/bar storage
|
||||
- trading calendar/timezone/currency 기본 처리
|
||||
- KIS adapter boundary
|
||||
- fixture 또는 mock provider를 통한 credential 없는 검증 경로
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [instrument-map] provider symbol과 ALT instrument identity를 매핑한다.
|
||||
- [ ] [daily-bars] 한국장 일봉 OHLCV를 normalized bar 모델로 저장한다.
|
||||
- [ ] [calendar-rules] `Asia/Seoul`, KRX, KRW 기준의 최소 calendar/currency 처리를 갖는다.
|
||||
- [ ] [kis-adapter] KIS provider adapter 경계가 worker 내부에 격리된다.
|
||||
- [ ] [mock-provider] KIS credential 없이도 pipeline을 검증할 fixture/mock provider가 있다.
|
||||
- [ ] [data-check] import 결과를 재현 가능하게 검증하는 테스트 또는 CLI/smoke 명령이 있다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] 선택된 한국장 universe의 일봉 데이터가 저장소에 들어간다.
|
||||
- [ ] 같은 입력을 다시 import해도 중복/갱신 정책이 일관된다.
|
||||
- [ ] normalized data가 backtest milestone에서 소비 가능한 형태로 조회된다.
|
||||
- [ ] `bin/test`와 관련 worker 검증이 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 미국장 데이터 수집
|
||||
- 분봉/틱/실시간 streaming
|
||||
- 실거래 주문 API
|
||||
- 고급 corporate action adjustment
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/worker/`, `packages/domain/market/`, `packages/contracts/proto/alt/v1/market.proto`
|
||||
- 표준선(선택): 첫 데이터 단위는 일봉이고, 구조는 분봉/실시간 확장을 막지 않는다.
|
||||
- 선행 작업: Persistence and Worker Backbone
|
||||
- 후속 작업: Backtest Engine Baseline
|
||||
- 확인 필요: MVP universe와 KIS credential 제공 방식
|
||||
58
agent-ops/roadmap/milestones/live-trading-boundary.md
Normal file
58
agent-ops/roadmap/milestones/live-trading-boundary.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Live Trading Boundary
|
||||
|
||||
## 목표
|
||||
|
||||
실거래 adapter, 주문 관리, 리스크 관리, 포트폴리오 동기화 경계를 paper trading 안정화 이후에 연다. 이 milestone은 실제 주문 제출을 서두르지 않고, broker adapter와 운영 안전장치를 먼저 명확히 하는 데 목적이 있다.
|
||||
|
||||
## 단계
|
||||
|
||||
거래 확장
|
||||
|
||||
## 상태
|
||||
|
||||
보류
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 잠금
|
||||
- 결정 필요: 아래 체크리스트
|
||||
- [ ] 실거래를 열기 전에 충족해야 할 paper trading 안정화 기준을 결정한다.
|
||||
- [ ] 첫 live broker/provider를 KIS로 고정할지 결정한다.
|
||||
- [ ] 실거래에서 허용할 주문 유형과 리스크 한도를 결정한다.
|
||||
|
||||
## 범위
|
||||
|
||||
- broker adapter boundary
|
||||
- order lifecycle
|
||||
- risk guard and kill switch
|
||||
- portfolio/account sync
|
||||
- audit log and operator confirmation
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [broker-port] broker adapter port가 paper/live 공통 경계를 갖는다.
|
||||
- [ ] [order-lifecycle] 주문 생성, 제출, 체결, 취소, 실패 lifecycle이 정의된다.
|
||||
- [ ] [risk-limits] 실거래 전 최소 risk limit과 kill switch가 있다.
|
||||
- [ ] [account-sync] 계좌/포지션 동기화 경계가 있다.
|
||||
- [ ] [audit-trail] live operation audit trail이 있다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] paper trading과 live trading 경계가 명확히 분리된다.
|
||||
- [ ] 실거래 주문 제출은 operator confirmation과 risk guard를 통과해야 한다.
|
||||
- [ ] live adapter 없이도 관련 domain/contract 테스트가 가능하다.
|
||||
- [ ] 사용자 결정 항목이 해소되기 전까지 구현 잠금이 유지된다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- MVP 단계 실거래 실행
|
||||
- 무인 자동 실거래
|
||||
- 고빈도/초단타 execution
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/worker/`, `services/api/`, `apps/client/`, `packages/domain/`
|
||||
- 표준선(선택): 실거래는 MVP 이후, paper trading 안정화 이후에만 연다.
|
||||
- 선행 작업: Paper Trading Readiness
|
||||
- 후속 작업: 없음
|
||||
- 확인 필요: paper 안정화 기준, live provider, 주문 유형, 리스크 한도
|
||||
57
agent-ops/roadmap/milestones/paper-trading-readiness.md
Normal file
57
agent-ops/roadmap/milestones/paper-trading-readiness.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Paper Trading Readiness
|
||||
|
||||
## 목표
|
||||
|
||||
실거래 전에 전략 실행, 가상 주문, 포지션, 리스크 흐름을 paper trading 경계에서 검증한다. 백테스트 기반을 실시간 또는 준실시간 실행 흐름으로 확장할 때 뒤집지 않을 adapter 경계를 만든다.
|
||||
|
||||
## 단계
|
||||
|
||||
거래 확장
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 잠금
|
||||
- 결정 필요: 아래 체크리스트
|
||||
- [ ] paper trading에서 사용할 초기 주문/체결 모델의 정밀도를 결정한다.
|
||||
- [ ] paper trading을 일봉 기반으로 시작할지, 분봉/실시간 가격까지 요구할지 결정한다.
|
||||
|
||||
## 범위
|
||||
|
||||
- paper account/portfolio state
|
||||
- virtual order and fill model
|
||||
- strategy execution scheduling
|
||||
- risk guard skeleton
|
||||
- API/client monitoring surface
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [paper-account] paper account와 portfolio state가 있다.
|
||||
- [ ] [virtual-orders] 가상 주문과 체결 모델이 있다.
|
||||
- [ ] [risk-guard] 최소 risk guard skeleton이 있다.
|
||||
- [ ] [strategy-run] 전략을 paper execution loop에서 실행할 수 있다.
|
||||
- [ ] [paper-monitor] client에서 paper state를 모니터링할 수 있다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] paper trading이 실제 broker 주문 없이 독립적으로 동작한다.
|
||||
- [ ] backtest engine과 공유할 개념과 분리할 개념이 문서화되어 있다.
|
||||
- [ ] 실거래 adapter가 들어와도 paper flow를 뒤집지 않는 경계가 있다.
|
||||
- [ ] 관련 테스트와 `bin/test`가 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 실거래 주문 제출
|
||||
- broker 계좌 잔고 실시간 동기화
|
||||
- 고급 리스크 엔진
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/worker/`, `services/api/`, `apps/client/`, `packages/domain/`
|
||||
- 표준선(선택): 실거래는 MVP 이후이며 paper trading 안정화 뒤에 연다.
|
||||
- 선행 작업: Flutter Operator Console
|
||||
- 후속 작업: Live Trading Boundary
|
||||
- 확인 필요: paper order/fill 정밀도와 데이터 시간 단위
|
||||
57
agent-ops/roadmap/milestones/persistence-worker-backbone.md
Normal file
57
agent-ops/roadmap/milestones/persistence-worker-backbone.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Persistence and Worker Backbone
|
||||
|
||||
## 목표
|
||||
|
||||
PostgreSQL과 Redis를 ALT의 운영 기본 인프라로 고정하고, worker가 import, normalization, backtest 같은 비동기 작업을 다룰 수 있는 durable backbone을 만든다.
|
||||
|
||||
## 단계
|
||||
|
||||
기반 정렬
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- PostgreSQL migration과 query generation 기준
|
||||
- Redis 사용 위치와 key prefix 기준
|
||||
- worker job 실행 모델
|
||||
- local infrastructure와 worker configuration 정합성
|
||||
- storage boundary와 domain mapping
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [db-migrations] PostgreSQL migration entrypoint가 있다.
|
||||
- [ ] [typed-queries] DB query를 type-safe하게 다루는 생성/검증 흐름이 있다.
|
||||
- [ ] [redis-boundary] Redis 사용 목적과 key prefix 기준이 worker 문서나 config에 정리되어 있다.
|
||||
- [ ] [job-model] worker가 비동기 작업을 표현하고 실행할 기본 job model을 갖는다.
|
||||
- [ ] [storage-ports] domain과 persistence 사이의 adapter/port 경계가 정해져 있다.
|
||||
- [ ] [infra-check] local PostgreSQL/Redis health를 확인하는 반복 가능한 절차가 있다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] local PostgreSQL/Redis를 실행한 뒤 worker가 필요한 설정을 읽을 수 있다.
|
||||
- [ ] migration/query generation 흐름이 문서화되어 있다.
|
||||
- [ ] worker job이 API 내부 구현에 의존하지 않는다.
|
||||
- [ ] `bin/test`, `bin/lint`, `bin/build`가 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 실제 KIS API 호출
|
||||
- backtest engine 전체 구현
|
||||
- production 배포 구성
|
||||
- broker/order/risk persistence
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/worker/`, `deployments/local/`, `packages/domain/`, `bin/`
|
||||
- 표준선(선택): PostgreSQL은 durable store, Redis는 보조 cache/queue/pubsub surface로 둔다.
|
||||
- 선행 작업: Workspace Baseline
|
||||
- 후속 작업: Korea Daily Data Foundation
|
||||
- 확인 필요: 없음
|
||||
56
agent-ops/roadmap/milestones/socket-session-loop.md
Normal file
56
agent-ops/roadmap/milestones/socket-session-loop.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Socket Session Loop
|
||||
|
||||
## 목표
|
||||
|
||||
Go API와 Flutter client 사이에 proto-socket 기반 최소 session loop를 만든다. 첫 loop는 handshake, request-response, disconnect/heartbeat 동작을 확인하는 데 집중하고, 무거운 데이터/백테스트 실행은 worker milestone로 넘긴다.
|
||||
|
||||
## 단계
|
||||
|
||||
기반 정렬
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- API socket server의 ALT payload parser 등록
|
||||
- Hello request/response handshake
|
||||
- Flutter client의 proto-socket connection wrapper
|
||||
- 최소 request-response smoke path
|
||||
- API/client socket loop 테스트 또는 수동 검증 명령
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [api-handshake] API가 ALT Hello request를 받고 Hello response를 반환한다.
|
||||
- [ ] [client-connect] Flutter client가 configured socket endpoint에 연결할 client layer를 갖는다.
|
||||
- [ ] [request-loop] 최소 request-response 메시지가 API와 client 사이에서 왕복한다.
|
||||
- [ ] [disconnect-state] client에서 연결/해제/오류 상태를 UI나 state layer에서 표현할 수 있다.
|
||||
- [ ] [socket-test] handshake loop를 검증하는 테스트 또는 반복 가능한 smoke 명령이 있다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] API와 client가 같은 contract typeName 기준으로 메시지를 주고받는다.
|
||||
- [ ] heartbeat/disconnect는 proto-socket 기본 동작을 따른다.
|
||||
- [ ] API가 long-running worker 작업을 직접 실행하지 않는다.
|
||||
- [ ] `bin/test`와 `bin/lint`가 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- market data import
|
||||
- backtest 실행
|
||||
- 인증/세션 권한 모델
|
||||
- 실시간 시세 streaming
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/api/`, `apps/client/`, `packages/contracts/`, `../proto-socket/`
|
||||
- 표준선(선택): API는 socket/session boundary를 맡고, worker execution은 worker milestone에서 다룬다.
|
||||
- 선행 작업: Contract and Codegen Baseline
|
||||
- 후속 작업: Flutter Operator Console
|
||||
- 확인 필요: 없음
|
||||
56
agent-ops/roadmap/milestones/us-market-expansion.md
Normal file
56
agent-ops/roadmap/milestones/us-market-expansion.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# US Market Expansion
|
||||
|
||||
## 목표
|
||||
|
||||
한국장 MVP에서 만든 provider-neutral market data와 backtest 구조 위에 미국장 데이터를 추가한다. KIS가 국내/해외를 모두 지원한다는 전제를 활용하되, 시장별 calendar, currency, venue 차이를 domain과 persistence에서 흡수한다.
|
||||
|
||||
## 단계
|
||||
|
||||
거래 확장
|
||||
|
||||
## 상태
|
||||
|
||||
계획
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 잠금
|
||||
- 결정 필요: 아래 체크리스트
|
||||
- [ ] 미국장 MVP universe를 ETF 중심, 개별주 중심, 또는 watchlist 중심 중 무엇으로 둘지 결정한다.
|
||||
- [ ] 미국장 데이터 provider를 KIS 우선으로 고정할지 보조 provider를 함께 고려할지 결정한다.
|
||||
|
||||
## 범위
|
||||
|
||||
- US market instrument mapping
|
||||
- USD/NASDAQ/NYSE calendar handling
|
||||
- daily bar import
|
||||
- 한국장과 동일한 normalized data/query path
|
||||
- backtest compatibility
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [ ] [us-instruments] 미국장 instrument identity와 provider symbol mapping이 있다.
|
||||
- [ ] [us-calendar] 미국장 timezone/currency/venue 기준이 있다.
|
||||
- [ ] [us-daily-bars] 미국장 일봉 데이터를 normalized bar model로 저장한다.
|
||||
- [ ] [shared-query] 한국장과 미국장이 같은 query/contract pattern을 공유한다.
|
||||
- [ ] [us-backtest] 미국장 daily data로 backtest fixture 또는 smoke가 동작한다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] 한국장 pipeline을 깨지 않고 미국장 데이터를 추가한다.
|
||||
- [ ] market/currency/venue 차이가 domain model과 contracts에 일관되게 반영된다.
|
||||
- [ ] `bin/test`와 관련 worker 검증이 통과한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 미국장 실거래 주문
|
||||
- 옵션/선물/FX
|
||||
- 분봉/실시간 미국장 streaming
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `services/worker/`, `packages/domain/market/`, `packages/contracts/proto/alt/v1/market.proto`
|
||||
- 표준선(선택): 시장 추가는 provider adapter와 market metadata 확장으로 처리하고 백테스트 코어를 복제하지 않는다.
|
||||
- 선행 작업: Korea Daily Data Foundation, Backtest Engine Baseline
|
||||
- 후속 작업: Live Trading Boundary
|
||||
- 확인 필요: 미국장 universe와 provider 우선순위
|
||||
58
agent-ops/roadmap/milestones/workspace-baseline.md
Normal file
58
agent-ops/roadmap/milestones/workspace-baseline.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Workspace Baseline
|
||||
|
||||
## 목표
|
||||
|
||||
ALT가 agent-first 방식으로 이어서 개발될 수 있도록 monorepo scaffold, Go workspace, Flutter client shell, agent-ops rules, README, root 검증 명령을 갖춘다.
|
||||
|
||||
## 단계
|
||||
|
||||
기반 정렬
|
||||
|
||||
## 상태
|
||||
|
||||
완료
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: 해제
|
||||
- 결정 필요: 없음
|
||||
|
||||
## 범위
|
||||
|
||||
- 루트 `go.work` 기반 multi-module scaffold
|
||||
- `services/api`, `services/worker`, `apps/cli`, `apps/client`, `packages/contracts`, `packages/domain` 경계
|
||||
- PostgreSQL/Redis local compose scaffold
|
||||
- agent-ops 초기화와 domain rules
|
||||
- README와 root helper scripts
|
||||
|
||||
## 필수 기능
|
||||
|
||||
- [x] [workspace-layout] runtime boundary 중심의 monorepo layout이 존재한다.
|
||||
- [x] [go-workspace] Go module들이 루트 `go.work`에 등록되어 있다.
|
||||
- [x] [flutter-client] Flutter client shell이 `apps/client`에 존재한다.
|
||||
- [x] [agent-rules] agent-ops root rules와 domain rules가 존재한다.
|
||||
- [x] [root-commands] `bin/test`, `bin/lint`, `bin/build`, `bin/dev`가 존재한다.
|
||||
- [x] [readme-entry] README가 현재 scaffold와 agent 작업 맥락을 설명한다.
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [x] `bin/test`가 통과한다.
|
||||
- [x] `bin/lint`가 통과한다.
|
||||
- [x] `bin/build`가 통과한다.
|
||||
- [x] README가 `agent-ops/skills/common/create-readme/SKILL.md` 기준 섹션을 포함한다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- 실제 KIS 연동
|
||||
- 실제 DB schema/migration
|
||||
- backtest engine 구현
|
||||
- Flutter 기능 화면 완성
|
||||
- 실거래 API 연동
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `README.md`, `go.work`, `bin/`, `agent-ops/`, `services/`, `apps/`, `packages/`
|
||||
- 표준선(선택): root entrypoint는 `bin/*`를 우선 사용하고, 도메인별 작업은 `agent-ops/rules/project/domain/*/rules.md`를 따른다.
|
||||
- 선행 작업: 없음
|
||||
- 후속 작업: Contract and Codegen Baseline
|
||||
- 확인 필요: 없음
|
||||
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>**: <어디까지가 이 도메인이고 어디서부터 저 도메인인지>
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- <이 도메인 코드에서 하면 안 되는 것>
|
||||
50
agent-ops/rules/common/rules-roadmap.md
Normal file
50
agent-ops/rules/common/rules-roadmap.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# 로드맵 규칙
|
||||
|
||||
`agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서만 적용한다.
|
||||
|
||||
## 로딩
|
||||
|
||||
- 세션 최초 1회 `agent-ops/roadmap/current.md`를 읽고 활성 Milestone 후보의 이름, 경로, 선택 규칙만 짧게 기억한다.
|
||||
- 활성 Milestone 후보는 `agent-ops/roadmap/milestones/` 하위 문서만 대상으로 한다.
|
||||
- Milestone의 목표, 주요 범위, 범위 제외는 선택한 활성 Milestone 문서에서 확인한다.
|
||||
- 일반 작업에서는 `ROADMAP.md`를 읽지 않는다.
|
||||
- `ROADMAP.md`는 로드맵 생성/갱신, Phase 전환, Milestone 추가/수정, 활성 Milestone 밖 작업 확인 때만 읽는다.
|
||||
- `agent-ops/roadmap/archive/**`는 사용자가 과거 Milestone 상세 확인이나 복원을 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
## Milestone 선택
|
||||
|
||||
- `current.md`는 현재 작업 위치가 아니라 활성 Milestone 후보 목록이다.
|
||||
- 기능 추가, 구조 변경, 스킬/문서 구조 변경 전에는 요청, 브랜치, 변경 파일, 관련 경로를 보고 관련 Milestone 문서를 1회 읽는다.
|
||||
- 선택한 Milestone의 목표 또는 범위 제외와 요청이 충돌하면 구현 전에 사용자에게 확인한다.
|
||||
- `current.md`가 아카이브 경로를 가리키면 그 항목은 활성 후보로 읽지 말고 로드맵 갱신이 필요하다고 보고한다.
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- `구현 잠금`은 승인 의식이 아니라 사용자 결정이 필요한지 표시하는 얇은 상태다.
|
||||
- 제품 방향, 범위, 우선순위, 책임 경계처럼 사용자만 결정할 수 있는 항목이 남아 있으면 상태를 `잠금`으로 두고 `결정 필요` 체크리스트에 질문을 적는다.
|
||||
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선이나 구현 가정으로 기록한다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||
- 선택한 Milestone에 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 사용자에게 확인한다.
|
||||
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 표준선으로 처리 가능한 작업을 막지 않는다.
|
||||
- 잠금 상태를 바꾸더라도 `필수 기능`이나 `완료 기준`을 자동 완료 처리하지 않는다.
|
||||
|
||||
## 필수 기능 item-id
|
||||
|
||||
- Milestone 문서의 `필수 기능` 체크리스트는 `- [ ] [item-id] 설명` 형식을 사용한다.
|
||||
- item-id는 공백 없는 짧은 ASCII 토큰이며, 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 `-`, `_`, `+`, `=`만 사용한다. 가능하면 1~3 segment를 우선하며, 전체 길이는 32자 이하를 권장한다.
|
||||
- item-id는 해당 Milestone 안에서만 유일하면 된다.
|
||||
- 다른 Milestone에서는 같은 item-id를 다시 사용할 수 있다. 여러 Milestone 후보에서 같은 item-id가 발견되면 Milestone 이름이나 문서 경로로 대상을 확정한다.
|
||||
- 사용자가 item-id를 언급하면 해당 Milestone의 `필수 기능` 항목을 우선 anchor로 삼고, 기존 item-id는 명시적 요청 없이 바꾸지 않는다.
|
||||
|
||||
## 작업 지점 분석
|
||||
|
||||
- 현재 작업 지점이나 남은 작업 분석 요청은 `analyze-roadmap-position` 스킬로 처리한다.
|
||||
- 분석 답변은 `agent-ops/skills/common/_templates/roadmap-position-report-template.md` 섹션과 필드 순서를 따른다.
|
||||
- 이때 `current.md`만으로 단정하지 말고 코드, git 상태, diff, 활성 Milestone 문서를 함께 본다.
|
||||
|
||||
## Milestone 아카이브
|
||||
|
||||
- 완료 또는 폐기되어 현재 작업 후보에서 제외할 Milestone은 `update-roadmap` 스킬로 아카이빙한다.
|
||||
- 아카이브 대상 문서는 `agent-ops/roadmap/archive/YYYY/MM/<milestone-slug>.md`로 이동한다.
|
||||
- 아카이빙할 때는 `ROADMAP.md`에 당시 요약만 남기고, 아카이브 문서 자체는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||
- 아카이브된 Milestone은 `current.md`에 남기지 않고, 일반 Milestone 선택이나 위치 분석의 후보로 삼지 않는다.
|
||||
28
agent-ops/rules/common/rules.md
Normal file
28
agent-ops/rules/common/rules.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 공통 규칙
|
||||
|
||||
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
|
||||
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
|
||||
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
|
||||
- 요청 범위를 넘는 변경을 하지 않는다.
|
||||
- 불확실하면 단정하지 말고 후보를 제시한다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
|
||||
**세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다.
|
||||
|
||||
1. `agent-ops/rules/project/rules.md`
|
||||
2. `agent-ops/rules/private/rules.md`
|
||||
3. `agent-ops/roadmap/` 디렉터리가 있으면 `agent-ops/rules/common/rules-roadmap.md`
|
||||
|
||||
# 스킬 규칙
|
||||
|
||||
**아래 경우에 부합되는지 반드시 끝까지 정독해서 읽고, 부합할 경우 `agent-ops/skills/common/router.md`를 작업 최초 1회 읽고 수행한다.** 자동으로 수행하지 않는다. **절대 스킵하지 말고 정독해야한다**
|
||||
- agent-ops 초기화
|
||||
- domain rule 생성
|
||||
- skill 생성
|
||||
- README 생성
|
||||
- 로드맵/마일스톤 생성·갱신
|
||||
- 현재 작업 지점 / 남은 작업 분석
|
||||
- 계획 작성 / plan 생성
|
||||
- 코드 리뷰 / review 진행
|
||||
- git commit / push
|
||||
- agent-ops 업데이트 / 진입 파일 재적용
|
||||
50
agent-ops/rules/project/domain/api/rules.md
Normal file
50
agent-ops/rules/project/domain/api/rules.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
domain: api
|
||||
last_rule_review_commit: no-commit-yet
|
||||
last_rule_updated_at: 2026-05-24
|
||||
---
|
||||
|
||||
# api
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
클라이언트-facing socket API endpoint를 제공한다. proto-socket server lifecycle, connection setup, heartbeat timing, and API configuration을 이 경계에서 관리한다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `services/api/cmd/alt-api/` - API service entrypoint
|
||||
- `services/api/internal/config/` - API environment configuration
|
||||
- `services/api/internal/socket/` - proto-socket server construction
|
||||
- `services/api/go.mod` - API module dependencies
|
||||
|
||||
## 제외 경로
|
||||
|
||||
- `services/worker/` - long-running jobs and backtest execution
|
||||
- `packages/contracts/` - protobuf schema source
|
||||
- `packages/domain/` - transport-free domain vocabulary
|
||||
- `apps/client/` - UI and client navigation
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
- `config.Config` - host, port, socket path, heartbeat interval, heartbeat wait
|
||||
- `config.Load` - environment variable parsing with local fallback defaults
|
||||
- `socket.NewServer` - proto-socket `WsServer` construction
|
||||
- `cmd/alt-api/main.go` - signal handling and service lifecycle
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
- Read configuration from environment variables with explicit local defaults.
|
||||
- Keep process lifecycle in `cmd/alt-api`; keep reusable socket construction under `internal/socket`.
|
||||
- Treat proto-socket as the transport abstraction; ALT payload parsing should be introduced deliberately from contracts.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
- **contracts**: API routes and parses messages according to contracts, but contract source stays in `packages/contracts`.
|
||||
- **worker**: API may enqueue or observe worker jobs, but should not run long backtest/import work inline.
|
||||
- **client**: API serves client sessions; client UI state and navigation stay in Flutter.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- Do not add direct Flutter/client assumptions to API internals.
|
||||
- Do not put scheduled job loops or heavy data processing in the API service.
|
||||
- Do not bypass proto-socket for the main client session path without an explicit architecture update.
|
||||
50
agent-ops/rules/project/domain/client/rules.md
Normal file
50
agent-ops/rules/project/domain/client/rules.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
domain: client
|
||||
last_rule_review_commit: no-commit-yet
|
||||
last_rule_updated_at: 2026-05-24
|
||||
---
|
||||
|
||||
# client
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
ALT의 Flutter client surface를 담당한다. web/mobile/desktop targets, application shell, routing, feature presentation, and client-side tests belong here.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `apps/client/lib/main.dart` - Flutter app bootstrap
|
||||
- `apps/client/lib/src/app/` - app shell, theme, router
|
||||
- `apps/client/lib/src/features/` - feature presentation code
|
||||
- `apps/client/test/` - Flutter widget/unit tests
|
||||
- `apps/client/pubspec.yaml` - Flutter package dependencies
|
||||
|
||||
## 제외 경로
|
||||
|
||||
- `services/api/` - socket server runtime
|
||||
- `packages/contracts/` - schema source for generated contracts
|
||||
- `packages/domain/` - Go domain models
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
- `AltClientApp` - Material app shell using Riverpod
|
||||
- `appRouterProvider` - `go_router` configuration
|
||||
- `DashboardScreen` - initial responsive dashboard surface
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
- Keep app-level shell and router under `lib/src/app`.
|
||||
- Put user-facing screens under the `lib/src/features/feature-name/presentation` pattern.
|
||||
- Use Material 3 components and responsive navigation patterns.
|
||||
- Test user-visible app shell behavior through Flutter tests.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
- **api**: client connects to API; server lifecycle and socket parsing stay in `services/api`.
|
||||
- **contracts**: client consumes generated/mapped contracts; protobuf source stays in `packages/contracts`.
|
||||
- **operations**: `bin/test`, `bin/lint`, and `bin/build` run client checks from the workspace root.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- Do not place backend service code or Go module files under `apps/client`.
|
||||
- Do not hand-edit platform generated files unless the Flutter platform integration explicitly requires it.
|
||||
- Do not hard-code production endpoint assumptions in presentation widgets.
|
||||
47
agent-ops/rules/project/domain/contracts/rules.md
Normal file
47
agent-ops/rules/project/domain/contracts/rules.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
domain: contracts
|
||||
last_rule_review_commit: no-commit-yet
|
||||
last_rule_updated_at: 2026-05-24
|
||||
---
|
||||
|
||||
# contracts
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
ALT 애플리케이션 레벨 protobuf 계약을 정의한다. proto-socket은 전송 계층으로 두고, ALT 메시지는 `PacketBase.data`에 실릴 payload schema로 관리한다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `packages/contracts/README.md` - contract direction and compatibility notes
|
||||
- `packages/contracts/proto/alt/v1/` - versioned protobuf schema source
|
||||
|
||||
## 제외 경로
|
||||
|
||||
- `packages/domain/` - internal Go domain types
|
||||
- `services/api/` - runtime socket server implementation
|
||||
- `apps/client/` - generated or consumed client-side integration
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
- `common.proto` - shared enums, decimal, handshake, and error messages
|
||||
- `market.proto` - instrument, price, quantity, bar, and market query messages
|
||||
- `backtest.proto` - backtest run spec, lifecycle, requests, responses, and result messages
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
- Prefer additive protobuf changes and reserve removal/renaming for explicit compatibility work.
|
||||
- Keep schema package under `alt.v1` until a deliberate version bump is planned.
|
||||
- Keep `option go_package` aligned with the generated Go package path.
|
||||
- Use explicit version/handshake messages because proto-socket protocol `0.1` does not carry an ALT application version field.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
- **api**: contracts define payload shape; API decides transport/session behavior.
|
||||
- **domain-model**: contracts are wire format; domain-model is internal business vocabulary.
|
||||
- **client**: client consumes generated or mapped contracts; schema source remains here.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- Do not hand-edit generated outputs.
|
||||
- Do not encode runtime server behavior or database concerns in `.proto` comments or fields.
|
||||
- Do not change field numbers for existing protobuf fields.
|
||||
49
agent-ops/rules/project/domain/domain-model/rules.md
Normal file
49
agent-ops/rules/project/domain/domain-model/rules.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
domain: domain-model
|
||||
last_rule_review_commit: no-commit-yet
|
||||
last_rule_updated_at: 2026-05-24
|
||||
---
|
||||
|
||||
# domain-model
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
ALT의 핵심 business vocabulary를 Go 타입으로 표현한다. market, instrument, price, bar, backtest run 같은 개념을 transport나 storage와 분리된 형태로 유지한다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `packages/domain/` - shared Go domain model module
|
||||
- `packages/domain/market/` - market, venue, currency, instrument, OHLCV bar types
|
||||
- `packages/domain/backtest/` - backtest run spec, run state, result types
|
||||
|
||||
## 제외 경로
|
||||
|
||||
- `packages/contracts/` - external protobuf schema representation
|
||||
- `services/api/` - socket transport and API boundary
|
||||
- `services/worker/` - execution and scheduled job boundary
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
- `market.Instrument` - tradable instrument identity and provider symbol mapping
|
||||
- `market.Bar` - timeframe OHLCV market data point
|
||||
- `backtest.RunSpec` - strategy, market, timeframe, period inputs for a run
|
||||
- `backtest.Run` - backtest lifecycle state
|
||||
- `backtest.Result` - backtest financial summary
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
- Domain type names should stay concise and market-neutral unless a market-specific rule is unavoidable.
|
||||
- Decimal values are represented as strings through `market.Decimal`; avoid float types for prices and quantities.
|
||||
- Keep package dependencies inward: domain packages should not import API, worker, CLI, Flutter, protobuf generated code, database drivers, or proto-socket.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
- **contracts**: domain-model owns internal Go vocabulary; contracts owns protobuf wire schema and compatibility.
|
||||
- **worker**: domain-model defines the shapes; worker executes imports, normalization, and backtests.
|
||||
- **api**: domain-model may be mapped to responses, but API transport details stay outside this module.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- Do not add persistence annotations, socket parser logic, or environment configuration here.
|
||||
- Do not introduce generated protobuf code into this package.
|
||||
- Do not use `float32` or `float64` for money, price, or quantity values.
|
||||
54
agent-ops/rules/project/domain/operations/rules.md
Normal file
54
agent-ops/rules/project/domain/operations/rules.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
domain: operations
|
||||
last_rule_review_commit: no-commit-yet
|
||||
last_rule_updated_at: 2026-05-24
|
||||
---
|
||||
|
||||
# operations
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
로컬 개발, workspace orchestration, operator CLI, and infrastructure entrypoints를 관리한다. 개발자가 반복적으로 쓰는 root-level commands and local services stay discoverable here.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `bin/` - workspace helper scripts
|
||||
- `go.work` - Go workspace module membership
|
||||
- `apps/cli/` - Go operator CLI for local/admin workflows
|
||||
- `deployments/local/` - local Docker Compose infrastructure
|
||||
- `.gitignore` - repository-level ignore policy
|
||||
|
||||
## 제외 경로
|
||||
|
||||
- `services/api/` - API runtime implementation
|
||||
- `services/worker/` - worker runtime implementation
|
||||
- `apps/client/` - Flutter client code
|
||||
- `packages/domain/` and `packages/contracts/` - shared model and schema sources
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
- `bin/dev` - prints local development entrypoints
|
||||
- `bin/test` - runs Go tests and Flutter tests
|
||||
- `bin/lint` - runs Go vet and Flutter analyze
|
||||
- `bin/build` - builds Go binaries and Flutter web
|
||||
- `deployments/local/docker-compose.yml` - PostgreSQL and Redis local stack
|
||||
- `apps/cli/cmd/alt/main.go` - operator CLI scaffold
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
- Keep root helper scripts executable, idempotent where practical, and `set -euo pipefail`.
|
||||
- Prefer root `bin/*` commands for whole-workspace workflows.
|
||||
- Keep local infrastructure defaults aligned with worker/API environment fallback values.
|
||||
- Add new Go modules to `go.work` when they are part of local development.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
- **api** and **worker**: operations starts, tests, and builds services; service behavior belongs to each service domain.
|
||||
- **client**: operations invokes Flutter commands; UI implementation stays under `apps/client`.
|
||||
- **contracts**: operations may run codegen later; schema design remains in contracts.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- Do not put application business logic in shell scripts.
|
||||
- Do not commit local secrets or machine-specific state.
|
||||
- Do not make root scripts silently skip failing module checks.
|
||||
47
agent-ops/rules/project/domain/worker/rules.md
Normal file
47
agent-ops/rules/project/domain/worker/rules.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
domain: worker
|
||||
last_rule_review_commit: no-commit-yet
|
||||
last_rule_updated_at: 2026-05-24
|
||||
---
|
||||
|
||||
# worker
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
데이터 수집, 정규화, backtest 실행, scheduled jobs처럼 오래 걸리거나 비동기적인 작업의 runtime surface를 담당한다. PostgreSQL과 Redis 연결 정보는 이 경계에서 운영 관점으로 다룬다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
- `services/worker/cmd/alt-worker/` - worker process entrypoint
|
||||
- `services/worker/internal/config/` - worker runtime configuration
|
||||
- `services/worker/go.mod` - worker module metadata
|
||||
|
||||
## 제외 경로
|
||||
|
||||
- `services/api/` - client-facing socket sessions
|
||||
- `packages/domain/` - shared domain types
|
||||
- `deployments/local/` - local infra orchestration
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
- `config.Config` - database and Redis URLs
|
||||
- `config.Load` - environment variable parsing with local development defaults
|
||||
- `cmd/alt-worker/main.go` - worker process bootstrap
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
- Keep external service configuration explicit through `DATABASE_URL` and `REDIS_URL`.
|
||||
- Put job orchestration and worker-specific adapters under `services/worker/internal`.
|
||||
- Use `packages/domain` for shared business shapes instead of redefining market/backtest concepts.
|
||||
|
||||
## 다른 도메인과의 경계
|
||||
|
||||
- **domain-model**: worker consumes domain-model types; it should not make domain-model depend on worker infrastructure.
|
||||
- **api**: API may request or observe work; worker owns execution.
|
||||
- **operations**: Docker Compose supplies local infrastructure; worker code owns runtime behavior.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- Do not make worker packages import API internals.
|
||||
- Do not hide required infrastructure in package-level globals.
|
||||
- Do not store generated contract code in the worker module.
|
||||
66
agent-ops/rules/project/rules.md
Normal file
66
agent-ops/rules/project/rules.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# ALT 프로젝트 규칙
|
||||
|
||||
## 응답 언어
|
||||
|
||||
- 기본 응답은 한국어로 작성한다.
|
||||
- 코드 식별자, 명령어, 경로, 에러 메시지는 원문 영어를 유지한다.
|
||||
- 설계 선택을 설명할 때는 ALT의 quant workspace 맥락과 연결해서 짧게 근거를 남긴다.
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
ALT는 개인 quant system workspace다. Go 서비스와 도구는 루트 `go.work`로 묶고, Flutter가 web/mobile/desktop 클라이언트 표면을 담당한다. 실시간 전송은 sibling workspace인 `../proto-socket/go`의 proto-socket 모듈을 사용하며, ALT 애플리케이션 계약은 `packages/contracts/proto`의 protobuf schema가 원천이다.
|
||||
|
||||
## 주요 구조
|
||||
|
||||
| 경로 | 역할 |
|
||||
|------|------|
|
||||
| `services/api/` | 클라이언트-facing proto-socket API endpoint |
|
||||
| `services/worker/` | import, normalization, backtest, scheduled job worker surface |
|
||||
| `apps/cli/` | 로컬/운영자 작업용 Go CLI |
|
||||
| `apps/client/` | Flutter client for web/mobile/desktop |
|
||||
| `packages/contracts/` | ALT protobuf contracts and compatibility notes |
|
||||
| `packages/domain/` | shared Go domain model for market and backtest concepts |
|
||||
| `deployments/local/` | local PostgreSQL and Redis development environment |
|
||||
| `bin/` | workspace-level helper entrypoints |
|
||||
|
||||
## 기술 스택
|
||||
|
||||
- Go 1.22 multi-module workspace via `go.work`.
|
||||
- `git.toki-labs.com/toki/proto-socket/go` is consumed through a local replace to `../proto-socket/go`.
|
||||
- `services/api` uses `nhooyr.io/websocket` through proto-socket server/client wrappers.
|
||||
- Contracts are protobuf schemas under `packages/contracts/proto/alt/v1`.
|
||||
- Flutter client uses Material 3, Riverpod, and `go_router`.
|
||||
- Local infrastructure uses Docker Compose with PostgreSQL 17 and Redis 7.
|
||||
|
||||
## 프로젝트 컨벤션
|
||||
|
||||
- 루트 작업은 `bin/dev`, `bin/test`, `bin/lint`, `bin/build`를 우선 사용한다.
|
||||
- Go 모듈 경계를 넘는 import는 `go.work`에 등록된 모듈 기준으로 유지한다.
|
||||
- protobuf generated client/server 코드는 schema에서 생성하고 손으로 편집하지 않는다.
|
||||
- `packages/domain`은 business vocabulary와 value object를 담고, transport나 persistence detail에 의존하지 않는다.
|
||||
- `services/api`는 socket/session boundary를 담당하고, domain 계산이나 worker job 실행을 직접 떠안지 않는다.
|
||||
- `services/worker`는 데이터 수집, 정규화, backtest 실행, scheduled job처럼 오래 걸리거나 비동기적인 일을 담당한다.
|
||||
- Flutter client는 `lib/src/app`에 앱 shell/router를 두고, 기능 화면은 `lib/src/features/feature-name/presentation` 패턴 아래에 둔다.
|
||||
- runtime configuration은 환경변수를 우선하고 로컬 개발 fallback을 둔다.
|
||||
|
||||
## 도메인 매핑
|
||||
|
||||
| 경로 패턴 | 도메인 | rules.md |
|
||||
|----------|--------|----------|
|
||||
| `packages/domain/**` | domain-model | `agent-ops/rules/project/domain/domain-model/rules.md` |
|
||||
| `packages/contracts/**` | contracts | `agent-ops/rules/project/domain/contracts/rules.md` |
|
||||
| `services/api/**` | api | `agent-ops/rules/project/domain/api/rules.md` |
|
||||
| `services/worker/**` | worker | `agent-ops/rules/project/domain/worker/rules.md` |
|
||||
| `apps/client/**` | client | `agent-ops/rules/project/domain/client/rules.md` |
|
||||
| `apps/cli/**`, `bin/**`, `deployments/local/**`, `go.work` | operations | `agent-ops/rules/project/domain/operations/rules.md` |
|
||||
|
||||
## 검증 명령
|
||||
|
||||
- 전체 테스트: `bin/test`
|
||||
- 전체 lint/analyze: `bin/lint`
|
||||
- 전체 build: `bin/build`
|
||||
- 로컬 실행 안내: `bin/dev`
|
||||
|
||||
## 스킬 라우팅
|
||||
|
||||
현재 프로젝트 전용 skill은 만들지 않는다. 반복 작업이 안정되면 `agent-ops/skills/project/` 아래에 추가한다.
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# 현재 로드맵 컨텍스트
|
||||
|
||||
## 활성 Milestone
|
||||
|
||||
- <milestone-name>: agent-ops/roadmap/milestones/<milestone-slug>.md
|
||||
|
||||
## 선택 규칙
|
||||
|
||||
- 이 문서는 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- 활성 Milestone은 `agent-ops/roadmap/milestones/` 하위 문서만 가리키며, `agent-ops/roadmap/archive/**`는 포함하지 않는다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 Milestone을 선택하고 같은 세션에서 1회 읽는다.
|
||||
- 활성 Milestone 둘 이상에 걸치면 필요한 Milestone 문서를 모두 읽고 작업 범위를 좁힌다.
|
||||
- 활성 Milestone 밖의 작업이면 `agent-ops/roadmap/ROADMAP.md`의 Milestone 목록을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 구현이나 구현 계획을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다. 관련 결정이 없고 표준선으로 처리 가능하면 잠금을 유지한 채 진행할 수 있으며, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# <Milestone 이름>
|
||||
|
||||
## 목표
|
||||
|
||||
<이 Milestone이 끝났을 때 달성되어야 하는 결과를 1~3문장으로 작성>
|
||||
|
||||
## 단계
|
||||
|
||||
<ROADMAP.md의 Phase 이름>
|
||||
|
||||
## 상태
|
||||
|
||||
<계획 | 진행 중 | 완료 | 보류 | 폐기>
|
||||
|
||||
## 구현 잠금
|
||||
|
||||
- 상태: <잠금 | 해제>
|
||||
- 결정 필요: <없음 | 아래 체크리스트>
|
||||
- [ ] <사용자만 결정할 수 있는 제품/범위/우선순위/책임 경계 질문>
|
||||
|
||||
## 범위
|
||||
|
||||
- <이 Milestone에 포함되는 제품/기술/문서 범위>
|
||||
|
||||
## 필수 기능
|
||||
|
||||
<!-- 필수 기능 항목은 `- [ ] [item-id] 설명` 형식을 사용한다. item-id는 공백 없는 짧은 ASCII 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 -_+= 만 사용한다. 전체 길이는 32자 이하를 권장한다. 해당 Milestone 안에서만 유일하면 되고, 다른 Milestone에서는 같은 item-id를 다시 사용할 수 있다. -->
|
||||
- [ ] [item-id] <구현 세부가 아니라 이 Milestone에서 달성해야 할 capability 또는 산출물>
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- [ ] <완료 여부를 확인할 수 있는 기준>
|
||||
|
||||
## 범위 제외
|
||||
|
||||
- <이 Milestone에서 의도적으로 하지 않는 일>
|
||||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `<path>`
|
||||
- 표준선(선택): <기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 진행할 기본 기준>
|
||||
- 선행 작업: <없음 또는 Milestone/태스크 이름>
|
||||
- 후속 작업: <없음 또는 Milestone/태스크 이름>
|
||||
- 확인 필요: <!-- TODO: 확인 필요 -->
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# 현재 작업 분석
|
||||
|
||||
- 추정 Milestone: <milestone-name 또는 복수 후보>
|
||||
- Milestone 링크: [<milestone-name>](agent-ops/roadmap/milestones/<milestone-slug>.md)
|
||||
- 신뢰도: <높음 | 중간 | 낮음>
|
||||
- 구현 잠금: <해제 | 잠금 | 정보 없음>
|
||||
- 결정 필요: <없음 | 현재 요청에 직접 영향을 주는 사용자 결정 항목 요약>
|
||||
- 한 줄 결론: <현재 작업 지점과 가장 중요한 다음 판단을 1문장으로 요약>
|
||||
|
||||
## 판단 근거
|
||||
|
||||
- 브랜치: <branch-name 또는 확인 불가>
|
||||
- 변경 파일: <없음 | N개, 핵심 경로 요약>
|
||||
- 로드맵 근거: <Milestone 목표/범위/필수 기능/완료 기준과 연결된 근거>
|
||||
- 코드/테스트 근거: <코드, 테스트, diff, 문서에서 확인한 근거>
|
||||
|
||||
## 구현된 것으로 보이는 부분
|
||||
|
||||
- 확인됨: [<item-id 또는 해당 없음>] <코드/문서/테스트 근거가 있는 완료 후보>
|
||||
|
||||
## 남은 작업
|
||||
|
||||
- 확인됨: [<item-id 또는 신규 id 필요>] <코드/문서/테스트 근거로 남았다고 볼 수 있는 작업>
|
||||
- 추정됨: [<item-id 또는 신규 id 필요>] <구조상 필요해 보이나 추가 확인이 필요한 작업>
|
||||
- 확인 필요: [<item-id 또는 신규 id 필요>] <사용자 판단, 범위 결정, 제품 의도가 필요한 작업>
|
||||
|
||||
## 위험/불확실성
|
||||
|
||||
- <없음 또는 신뢰도를 낮춘 이유, 누락된 근거, 잠금/링크/템플릿 문제>
|
||||
|
||||
## 다음 행동
|
||||
|
||||
- 우선순위 1: <가장 먼저 할 작업 또는 확인>
|
||||
- 우선순위 2: <다음 작업 또는 확인>
|
||||
- 사용자 확인 필요: <없음 또는 현재 요청에 직접 영향을 주는 사용자 결정 질문>
|
||||
|
||||
## 읽은 주요 파일
|
||||
|
||||
- <path>
|
||||
38
agent-ops/skills/common/_templates/roadmap-template.md
Normal file
38
agent-ops/skills/common/_templates/roadmap-template.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# 로드맵
|
||||
|
||||
## 전체 목표
|
||||
|
||||
<프로젝트가 최종적으로 달성하려는 결과를 1~3문장으로 작성>
|
||||
|
||||
## Phase 흐름
|
||||
|
||||
- <Phase 이름>: <이 Phase의 목표와 역할>
|
||||
|
||||
## Milestone 목록
|
||||
|
||||
### <Phase 이름>
|
||||
|
||||
- [<Milestone 이름>](milestones/<milestone-slug>.md) - 상태: <계획 | 진행 중 | 완료 | 보류 | 폐기>; 목표: <짧은 목표 요약>
|
||||
|
||||
## 아카이브 Milestone 요약
|
||||
|
||||
<!-- archive 항목 형식: - <Milestone 이름> - 상태: <완료 | 폐기>; 아카이브일: <YYYY-MM-DD>; 요약: <1문장>; 핵심 산출물/근거: <짧은 근거>; 후속 영향: <없음 또는 후속 Milestone/작업> -->
|
||||
- 없음
|
||||
|
||||
## 로딩 정책
|
||||
|
||||
- 일반 작업에서는 `agent-ops/roadmap/ROADMAP.md`를 매번 읽지 않는다.
|
||||
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-ops/roadmap/current.md`를 먼저 읽는다.
|
||||
- `current.md`는 현재 작업 위치가 아니라 활성 Milestone 후보 목록이다.
|
||||
- `current.md`에는 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
|
||||
- `current.md`의 활성 Milestone은 `agent-ops/roadmap/milestones/` 하위 문서만 가리키며, `agent-ops/roadmap/archive/**`는 포함하지 않는다.
|
||||
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 활성 Milestone 문서를 같은 세션에서 1회 읽는다.
|
||||
- 활성 Milestone 밖의 작업이면 이 문서의 Milestone 목록을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||
- 이 문서는 로드맵 생성/갱신, Phase 전환, Milestone 추가/수정 요청이 있을 때만 읽는다.
|
||||
- 상세 작업과 완료 기준은 각 Milestone 문서의 체크리스트로 관리한다.
|
||||
- 완료 또는 폐기되어 아카이브된 Milestone은 이 문서의 `아카이브 Milestone 요약`에 당시 요약만 남기고, 아카이브 문서 링크나 상세 경로는 남기지 않는다.
|
||||
- 상세 문서가 있는 `agent-ops/roadmap/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
|
||||
- 아카이브된 Milestone 문서는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
|
||||
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획 생성, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
|
||||
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조/도메인 rule/플랫폼 관례로 정할 수 있는 작업은 표준선으로 기록하고 진행할 수 있다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
57
agent-ops/skills/common/_templates/skill-template.md
Normal file
57
agent-ops/skills/common/_templates/skill-template.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
name: <skill-name>
|
||||
version: 1.0.0
|
||||
description: <이 skill이 하는 일을 한 줄로 설명. 트리거 키워드 포함 권장>
|
||||
depends: [<other-skill>] # 선택 — 의존 skill이 없으면 이 줄 삭제
|
||||
---
|
||||
|
||||
# <skill-name>
|
||||
|
||||
## 목적
|
||||
|
||||
<이 skill이 해결하는 문제를 1~2문장으로 설명>
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- <이 skill을 호출해야 하는 상황 1>
|
||||
- <이 skill을 호출해야 하는 상황 2>
|
||||
- <이 skill을 호출해야 하는 상황 3>
|
||||
|
||||
## 입력
|
||||
|
||||
- `<param-name>`: <설명> (필수)
|
||||
- `<param-name>`: <설명> (선택)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] <실행 전 반드시 확인해야 할 조건 1>
|
||||
- [ ] <실행 전 반드시 확인해야 할 조건 2>
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **<단계명>**
|
||||
- <세부 행동>
|
||||
- <세부 행동>
|
||||
|
||||
2. **<단계명>**
|
||||
- <세부 행동>
|
||||
|
||||
3. **결과 보고**
|
||||
- <출력할 내용>
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] <실행 후 확인해야 할 성공 조건 1>
|
||||
- [ ] <실행 후 확인해야 할 성공 조건 2>
|
||||
- 검증 실패 시: <실패 시 취할 행동 — 롤백, 사용자 알림, 재시도 등>
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```
|
||||
<출력 예시>
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- <절대 하면 안 되는 것>
|
||||
- <절대 하면 안 되는 것>
|
||||
109
agent-ops/skills/common/analyze-roadmap-position/SKILL.md
Normal file
109
agent-ops/skills/common/analyze-roadmap-position/SKILL.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
name: analyze-roadmap-position
|
||||
version: 1.5.0
|
||||
description: "지금 작업이 뭐지?, 현재 작업 분석, 남은 작업 확인 요청에 대해 활성 Milestone과 코드 상태를 함께 읽어 현재 작업 지점, Milestone 문서 링크, 남은 일을 추정하는 읽기 전용 스킬"
|
||||
---
|
||||
|
||||
# 작업 지점 분석
|
||||
|
||||
## 목적
|
||||
|
||||
현재 브랜치, 변경 파일, 코드 구조, 활성 Milestone 문서를 함께 분석해 지금 작업이 어느 Milestone에 걸쳐 있는지와 남은 작업 후보를 보고한다.
|
||||
결과에는 추정한 Milestone의 문서 링크를 항상 함께 출력한다.
|
||||
Milestone의 `필수 기능` 항목에 item-id가 있으면 남은 작업과 판단 근거에 함께 표시해 사용자가 짧은 id로 후속 지시를 할 수 있게 한다.
|
||||
결과 보고는 `agent-ops/skills/common/_templates/roadmap-position-report-template.md` 템플릿의 섹션, 필드, 순서를 그대로 따라 작성한다.
|
||||
`current.md`만 보고 현재 작업 위치를 단정하지 않고, 실제 코드 상태와 요청 내용을 근거로 판단한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "지금 작업이 뭐지?", "현재 작업이 뭐야?", "어디까지 했지?"라고 물을 때
|
||||
- 사용자가 현재 브랜치 또는 변경 파일 기준으로 남은 작업을 알고 싶어 할 때
|
||||
- 활성 Milestone 안에서 이번 요청이 어느 범위에 속하는지 확인해야 할 때
|
||||
- 구현 전에 로드맵 기준 작업 위치를 가볍게 점검해야 할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `question`: 사용자의 현재 작업 지점 질문 또는 남은 작업 질문 (선택)
|
||||
- `scope`: 분석할 경로, 기능명, 도메인명, 브랜치명 힌트 (선택)
|
||||
- `depth`: `quick` 또는 `deep` (선택, 없으면 `quick`)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽어 최신 답변 템플릿 확인
|
||||
- [ ] `agent-ops/roadmap/current.md` 존재 여부 확인
|
||||
- [ ] `current.md`의 활성 Milestone 목록이 가리키는 문서 존재 여부 확인
|
||||
- [ ] 활성 Milestone 목록이 `agent-ops/roadmap/archive/**` 경로를 가리키지 않는지 확인
|
||||
- [ ] 활성 Milestone 이름과 문서 경로를 결과 출력에 쓸 Markdown 링크로 기록
|
||||
- [ ] git 저장소이면 현재 브랜치, `git status --short`, 변경 파일 목록 확인
|
||||
- [ ] 변경 파일이 있으면 `agent-ops/rules/project/rules.md`의 도메인 매핑 기준으로 관련 domain rule 확인
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **활성 Milestone 창 확인**
|
||||
- `agent-ops/roadmap/current.md`를 읽고 활성 Milestone 후보와 선택 규칙을 파악한다.
|
||||
- `current.md`의 후보가 `agent-ops/roadmap/archive/**`를 가리키면 해당 문서는 읽지 말고 로드맵 갱신 필요 항목으로 기록한다.
|
||||
- 활성 Milestone 문서를 모두 읽되, 목록이 많으면 사용자 요청이나 변경 파일과 관련 높은 문서부터 읽는다.
|
||||
- 읽은 Milestone은 `<milestone-name>: <path>` 형태로 보존하고, 결과 보고에서는 `[<milestone-name>](<path>)` Markdown 링크로 출력한다.
|
||||
- `current.md`가 없거나 형식이 맞지 않으면 `agent-ops/roadmap/ROADMAP.md`의 Milestone 목록을 확인하고 불확실성을 보고한다.
|
||||
|
||||
2. **작업 흔적 확인**
|
||||
- git 저장소이면 `git branch --show-current`, `git status --short`, `git diff --name-only`, 필요 시 `git diff --stat`을 확인한다.
|
||||
- 변경 파일이 없으면 사용자의 요청 문장과 최근 대상 경로 힌트를 기준으로 추정한다.
|
||||
- 변경 파일이 있으면 관련 코드와 테스트 파일을 필요한 만큼만 읽는다.
|
||||
|
||||
3. **Milestone 매칭**
|
||||
- 활성 Milestone의 목표, 범위, 완료 기준, 범위 제외 항목과 변경 파일/요청 내용을 비교한다.
|
||||
- 활성 Milestone의 `필수 기능` 체크리스트를 확인하고, 관련 항목에 item-id가 있으면 판단 근거와 남은 작업에 item-id를 함께 기록한다.
|
||||
- 여러 Milestone 후보에서 같은 item-id가 보이면 item-id만으로 위치를 확정하지 말고 Milestone 이름과 문서 링크를 함께 제시한다.
|
||||
- 활성 Milestone의 `구현 잠금` 섹션, 상태, `결정 필요` 항목을 함께 확인한다. 섹션이 없거나 상태가 `잠금`이면 현재 요청에 직접 영향을 주는 사용자 결정 항목과 배경 미정 항목을 구분해 보고하고, 결정이 모두 정해진 작업이면 로드맵에서 해제 가능하다고 보고한다.
|
||||
- 하나의 Milestone에 명확히 속하면 단일 후보로 보고한다.
|
||||
- 둘 이상의 Milestone에 걸치면 복수 후보로 보고하고, 어떤 파일이나 기능이 어느 Milestone에 닿는지 나눈다.
|
||||
- 활성 Milestone 밖으로 보이면 `ROADMAP.md`의 Milestone 목록을 확인하고 전환 또는 신규 Milestone 필요성을 제안한다.
|
||||
|
||||
4. **남은 작업 분류**
|
||||
- `확인됨`: 코드, 문서, 테스트, diff로 근거가 있는 남은 작업
|
||||
- `추정됨`: 구조상 필요해 보이지만 추가 확인이 필요한 작업
|
||||
- `확인 필요`: 현재 요청에 직접 영향을 주는 제품 판단, 범위 결정, 사용자 의도가 필요한 작업
|
||||
- 완료 여부는 evidence 없이 확정하지 않는다.
|
||||
|
||||
5. **결과 보고**
|
||||
- `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 기준으로 출력한다.
|
||||
- 템플릿의 섹션 제목, 필드명, 순서를 바꾸지 않는다.
|
||||
- 템플릿의 모든 필드를 채우며, 근거가 없으면 생략하지 말고 `없음`, `확인 불가`, `확인 필요` 중 하나로 명시한다.
|
||||
- `판단 근거`에는 브랜치, 변경 파일, 로드맵 근거, 코드/테스트 근거를 각각 분리해 적는다.
|
||||
- `남은 작업`은 `확인됨`, `추정됨`, `확인 필요` 세 분류를 모두 유지한다.
|
||||
- `다음 행동`에는 가장 우선해야 할 실행 또는 확인을 1~2개만 적는다.
|
||||
- `읽은 주요 파일`에는 실제로 읽은 핵심 파일만 적는다.
|
||||
|
||||
Milestone을 하나로 확정할 수 없으면 후보 Milestone마다 링크를 출력한다.
|
||||
Milestone 문서 경로를 찾지 못한 경우에도 링크 항목을 생략하지 말고 `링크 확인 불가: <이유>`와 확인한 로드맵 파일 경로를 함께 적는다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `roadmap-position-report-template.md`를 읽고 그 섹션 순서와 필드명을 유지했는가
|
||||
- [ ] `current.md`만 근거로 현재 위치를 단정하지 않았는가
|
||||
- [ ] 활성 Milestone 문서의 목표와 범위 제외 항목을 확인했는가
|
||||
- [ ] `agent-ops/roadmap/archive/**` 문서를 명시 요청 없이 읽지 않았는가
|
||||
- [ ] 활성 Milestone 문서의 `구현 잠금` 섹션 존재 여부, 상태, `결정 필요` 항목을 확인했는가
|
||||
- [ ] 추정 Milestone마다 문서 링크를 출력했는가
|
||||
- [ ] 관련 `필수 기능` 항목에 item-id가 있으면 결과에 함께 표시했는가
|
||||
- [ ] 변경 파일 또는 사용자 요청과 Milestone 판단 근거가 연결되어 있는가
|
||||
- [ ] 남은 작업을 `확인됨`, `추정됨`, `확인 필요`로 구분했는가
|
||||
- [ ] 템플릿 필드를 근거 없이 생략하지 않고 `없음`, `확인 불가`, `확인 필요`로 채웠는가
|
||||
- [ ] 로드맵 파일을 수정하지 않았는가
|
||||
- 검증 실패 시: 부족한 근거를 명시하고 신뢰도를 낮춘다. Milestone 링크 누락은 출력 전 반드시 보정한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
- 템플릿 경로: `agent-ops/skills/common/_templates/roadmap-position-report-template.md`
|
||||
- 템플릿을 그대로 복사해 placeholder를 채운다.
|
||||
- 섹션 제목과 필드명을 임의로 번역, 축약, 삭제하지 않는다.
|
||||
- 값이 없는 필드는 `없음`, `확인 불가`, `확인 필요` 중 하나로 채운다.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- `current.md`만 읽고 현재 작업 위치를 확정하지 않는다.
|
||||
- 사용자가 명시하지 않은 상태에서 `ROADMAP.md`, `current.md`, Milestone 문서를 수정하지 않는다.
|
||||
- 사용자가 명시하지 않은 상태에서 `agent-ops/roadmap/archive/**`를 읽지 않는다.
|
||||
- evidence 없이 Milestone이나 기능을 완료 처리하지 않는다.
|
||||
- 활성 Milestone 밖 작업을 임의로 새 Milestone으로 추가하지 않는다.
|
||||
336
agent-ops/skills/common/code-review/SKILL.md
Normal file
336
agent-ops/skills/common/code-review/SKILL.md
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
---
|
||||
name: code-review
|
||||
description: Use for active task review requests such as 리뷰 진행해, 리뷰해줘, 코드 리뷰해줘, code review, CODE_REVIEW.md, 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 immediately writes follow-up PLAN/CODE_REVIEW files. Never stop after verdict append.
|
||||
---
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
## Core Loop Rules
|
||||
|
||||
- Trigger: Korean or English active-task review requests, including `리뷰 진행해` and `리뷰해줘`, must use this skill when an active `CODE_REVIEW-*-G??.md` exists under `agent-task/*/` or `agent-task/*/*/`, excluding `agent-task/archive/**`.
|
||||
- Finalize every selected active review: append one verdict, archive the active review and plan files, then create exactly one next state before reporting.
|
||||
- Next state: `PASS` writes `complete.log` and moves the task under `agent-task/archive/YYYY/MM/`; `WARN` or `FAIL` writes the next active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md`.
|
||||
- Do not ask for confirmation before WARN/FAIL follow-up files. 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, resume at Step 5 and finish finalization first.
|
||||
|
||||
## 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/`, using a short snake_case name such as `refactoring`.
|
||||
- `{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.
|
||||
|
||||
Review routing rules:
|
||||
|
||||
- `local`: narrow, low-risk, or first-pass review where tests and scope are clear.
|
||||
- `cloud`: multi-file, API/call-site impact, meaningful test judgment, plan deviation, weak verification, security/auth, storage/migration, concurrency, protocol/schema, cross-domain, or repeated Required issues.
|
||||
- `cloud-G07` or higher is mandatory for terminal-agent follow-up work: shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, or terminal benchmark-style tasks. Merely running deterministic tests such as `go test` does not make a task terminal-agent work.
|
||||
- `cloud-G07` or higher is mandatory for follow-up plans when a local implementation failed a real bin/smoke/integration command after unit tests passed, when the success condition depends on an interactive TUI/PTY/browser/external CLI or screen repaint/cursor stream, or when verification trust is Fail because recorded stdout/stderr does not match a rerun.
|
||||
|
||||
Directory states:
|
||||
|
||||
| State | Meaning |
|
||||
|-------|---------|
|
||||
| `PLAN-*-G??.md` + `CODE_REVIEW-*-G??.md` stub or placeholders | Implementation is pending/incomplete; review should fail completeness if invoked |
|
||||
| `PLAN-*-G??.md` + filled `CODE_REVIEW-*-G??.md` | Ready for code-review skill |
|
||||
| `complete.log` + `*.log` files | Task complete (PASS), before final task-directory archive move |
|
||||
| `agent-task/archive/YYYY/MM/{task_name}/complete.log` + `*.log` files | Archived completed task path (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`
|
||||
|
||||
| Result | Action |
|
||||
|--------|--------|
|
||||
| Exactly one | Review that task; exactly one `PLAN-*-G??.md` is expected beside it |
|
||||
| None | Nothing to review; stop and report |
|
||||
| Multiple | If the user/runtime named a task group, task path, or subtask directory that identifies exactly one active review file, review that directory. Otherwise list paths and ask which task to review; do not choose by agent judgment. |
|
||||
|
||||
## 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 `구현 체크리스트`; item text/order must match.
|
||||
- Confirm the implementation marked the matching checklist items in the active review file, including the final mandatory `CODE_REVIEW-*-G??.md` completion item.
|
||||
- Treat blank placeholder sections, missing actual implementation notes, missing checklist completion, or missing actual stdout/stderr in the active review file as a completeness or verification-trust failure.
|
||||
- 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 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 |
|
||||
| `FAIL` | One or more Required issues. | Yes |
|
||||
|
||||
Issue severity:
|
||||
|
||||
- `Required`: correctness, API contract, missing required test, plan-completeness issue, or incomplete/placeholder `CODE_REVIEW-*-G??.md` content required from the implementing agent.
|
||||
- `Suggested`: useful improvement that should enter the loop but does not block correctness.
|
||||
- `Nit`: tiny cleanup; may be recorded 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`. 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.
|
||||
|
||||
## Step 6 - Post-Review Actions
|
||||
|
||||
For `PASS`, write `agent-task/{task_name}/complete.log` before reporting.
|
||||
|
||||
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`.
|
||||
- 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`, 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>`.
|
||||
- Base the follow-up scope directly on the archived review findings. Keep it narrow and actionable.
|
||||
- Choose lane/grade again; preserve the prior route only when it was adequate, otherwise raise `GNN` and/or move `local -> cloud`.
|
||||
- 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, move the follow-up build lane to `cloud` unless the issue is trivially deterministic and review-detectable without live environment behavior.
|
||||
- If the follow-up work is terminal-agent work (shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, or terminal benchmark-style tasks), use `cloud-G07` or higher.
|
||||
- If unit tests passed but a real bin/smoke/integration command failed, 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, use `cloud-G07` or higher.
|
||||
- If recorded verification output was reconstructed, stale, or mismatched on rerun, use `cloud-G07` or higher and make verification trust recovery a plan item.
|
||||
- `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.
|
||||
|
||||
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.
|
||||
> 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}
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[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이면 다음 active plan/review 파일을 즉시 작성한다.
|
||||
4. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.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`로 아카이브한다.
|
||||
- [ ] 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 split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
{pre-filled from plan — one bullet per review focus area}
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
|
||||
### {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), 리뷰 에이전트 지시 | 스텁 생성 시 고정 | 구현 에이전트가 수정하거나 실행하지 않음 |
|
||||
| 구현 항목별 완료 여부 (항목명) | 스텁 생성 시 고정 | `[ ]` → `[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.
|
||||
- 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 `WARN` or `FAIL`, open `agent-task/{task_name}/code_review_{review_lane}_GNN_N.log`.
|
||||
- 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, or follow-up plan/review 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, and for `PASS` the final task archive move.
|
||||
|
||||
Report Required/Suggested counts, archive names, and the final task archive path for `PASS` or new plan path for `WARN`/`FAIL`.
|
||||
|
||||
## Review Dimensions
|
||||
|
||||
| Dimension | Check |
|
||||
|-----------|-------|
|
||||
| Correctness | Logic, edge cases, concurrency, errors |
|
||||
| Completeness | All planned checklist items done, including matching plan/review `구현 체크리스트` completion |
|
||||
| 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.
|
||||
- No active `.md` files remain after PASS.
|
||||
- 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 split: empty active parent `agent-task/{task_group}/` removed after the subtask move; non-empty parent left in place.
|
||||
- WARN/FAIL: new active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md` created with matching headers and matching `구현 체크리스트`; no `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 continue task loops"
|
||||
default_prompt: "Use $code-review to review the active repository task, archive active files, and create complete.log or follow-up plan/review files."
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Complete - {task_name}
|
||||
|
||||
## 완료 일시
|
||||
|
||||
{YYYY-MM-DD or ISO-8601}
|
||||
|
||||
## 요약
|
||||
|
||||
{one-line task summary, loop count, and final verdict}
|
||||
|
||||
## 루프 이력
|
||||
|
||||
| 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} |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
- {implemented or cleaned-up change}
|
||||
|
||||
## 최종 검증
|
||||
|
||||
- `{command}` - {PASS/FAIL/BLOCKED}; {actual output summary or saved output path}
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
124
agent-ops/skills/common/commit-push/SKILL.md
Normal file
124
agent-ops/skills/common/commit-push/SKILL.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
name: commit-push
|
||||
version: 1.0.0
|
||||
description: 변경 사항을 커밋하고 원격에 푸시한다. "커밋해줘", "푸시해줘", "커밋하고 푸시" 요청 시 사용한다.
|
||||
---
|
||||
|
||||
# commit-push
|
||||
|
||||
## 목적
|
||||
|
||||
현재 변경 내용을 분석하여 한국어 커밋 메시지를 작성하고, 커밋 및 푸시를 수행한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- "커밋해줘", "커밋하고 푸시해줘" 요청 시
|
||||
- "변경 사항 올려줘", "푸시해줘" 요청 시
|
||||
- 코드 작업 완료 후 "반영해줘", "올려줘" 요청 시
|
||||
|
||||
## 입력
|
||||
|
||||
- `scope`: 커밋 범위 — all(전체) 또는 특정 파일/경로 (선택, 기본값: all)
|
||||
- `push`: 푸시 여부 (선택, 기본값: true)
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] 커밋할 변경 사항이 존재하는가 (`git status`로 확인)
|
||||
- [ ] 현재 브랜치가 올바른 브랜치인가
|
||||
- [ ] `.env`, 시크릿 파일 등 민감한 파일이 스테이징에 포함되어 있지 않은가
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **변경 사항 파악**
|
||||
- `git status`로 변경/추가/삭제된 파일 목록을 확인한다
|
||||
- `git diff`로 구체적인 변경 내용을 확인한다
|
||||
- 변경 사항이 없으면 사용자에게 알리고 종료한다
|
||||
|
||||
2. **민감 파일 검사**
|
||||
- 스테이징 대상에 아래 패턴이 포함되면 해당 파일을 제외하고 사용자에게 경고한다
|
||||
- `.env`, `.env.*`
|
||||
- `*secret*`, `*credential*`, `*password*`
|
||||
- `*.pem`, `*.key`, `*.p12`
|
||||
- `.gitignore`에 이미 등록된 파일은 무시한다
|
||||
|
||||
3. **커밋 메시지 작성**
|
||||
- 변경 내용을 분석하여 한국어로 커밋 메시지를 작성한다
|
||||
- 아래 메시지 규칙을 따른다
|
||||
|
||||
4. **사용자 확인**
|
||||
- 커밋 메시지와 대상 파일 목록을 보여주고 승인을 받는다
|
||||
- 사용자가 메시지 수정을 요청하면 반영한다
|
||||
|
||||
5. **커밋 실행**
|
||||
- scope에 따라 파일을 스테이징한다
|
||||
- all: 변경된 전체 파일을 개별적으로 `git add`
|
||||
- 특정 경로: 해당 파일만 `git add`
|
||||
- 승인된 메시지로 `git commit`을 실행한다
|
||||
|
||||
6. **푸시 실행**
|
||||
- push가 true인 경우에만 실행한다
|
||||
- 현재 브랜치를 원격에 푸시한다
|
||||
- 원격 브랜치가 없으면 `-u origin {branch}`로 설정한다
|
||||
- 충돌 발생 시 사용자에게 알리고 중단한다
|
||||
|
||||
7. **결과 보고**
|
||||
- 커밋 해시, 메시지, 변경 파일 수, 푸시 결과를 출력한다
|
||||
|
||||
## 커밋 메시지 규칙
|
||||
|
||||
### 형식
|
||||
|
||||
```
|
||||
<타입>: <변경 요약>
|
||||
|
||||
<본문> (선택)
|
||||
```
|
||||
|
||||
### 타입 목록
|
||||
|
||||
| 타입 | 용도 |
|
||||
|------|------|
|
||||
| 기능 | 새로운 기능 추가 |
|
||||
| 수정 | 버그 수정 |
|
||||
| 개선 | 기존 기능 개선, 리팩토링 |
|
||||
| 문서 | 문서 추가/수정 |
|
||||
| 설정 | 빌드, CI/CD, 설정 파일 변경 |
|
||||
| 테스트 | 테스트 추가/수정 |
|
||||
| 정리 | 코드 정리, 불필요 코드 제거 |
|
||||
|
||||
### 작성 원칙
|
||||
|
||||
- **한국어**로 작성한다
|
||||
- 요약은 50자 이내로 간결하게 작성한다
|
||||
- 요약은 "~한다" 형태의 서술형으로 끝낸다 (예: "로그인 검증 로직을 추가한다")
|
||||
- 본문은 **무엇을** 변경했는지가 아니라 **왜** 변경했는지를 쓴다
|
||||
- 변경 파일이 3개 이하이면 본문을 생략할 수 있다
|
||||
- 여러 성격의 변경이 섞여 있으면 가장 핵심적인 변경을 기준으로 타입을 정한다
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```
|
||||
## 커밋 완료
|
||||
|
||||
- 브랜치: {브랜치명}
|
||||
- 커밋: {해시} — {커밋 메시지 요약}
|
||||
- 변경 파일: {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`를 사용하지 않는다
|
||||
- 사용자 확인 없이 커밋하지 않는다
|
||||
- 영어로 커밋 메시지를 작성하지 않는다
|
||||
- 변경 내용과 무관한 커밋 메시지를 작성하지 않는다
|
||||
- `--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 파일 생성만 담당한다
|
||||
153
agent-ops/skills/common/create-readme/SKILL.md
Normal file
153
agent-ops/skills/common/create-readme/SKILL.md
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
---
|
||||
name: create-readme
|
||||
version: 1.0.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-ops/roadmap/current.md`가 있으면 README에 현재 작업 위치를 복사하지 말고, 로드맵을 확인할 문서 경로만 적는다.
|
||||
- README는 제품 소개 문서이면서 작업 진입점이다. 마케팅 문구보다 실행 가능한 정보와 프로젝트 경계를 우선한다.
|
||||
- 불확실한 내용은 단정하지 않고 `TODO` 또는 "확인 필요"로 남긴다.
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] 루트 `README.md` 존재 여부와 기존 내용 확인
|
||||
- [ ] `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `Makefile`, `docker-compose.yml` 등 실행/검증 명령 근거 확인
|
||||
- [ ] `agent-ops/rules/project/rules.md`가 있으면 프로젝트 개요, 기술 스택, 도메인 매핑 확인
|
||||
- [ ] `agent-ops/roadmap/ROADMAP.md` 또는 `agent-ops/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에 길게 복사하지 않는다.
|
||||
215
agent-ops/skills/common/create-roadmap/SKILL.md
Normal file
215
agent-ops/skills/common/create-roadmap/SKILL.md
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
---
|
||||
name: create-roadmap
|
||||
version: 1.9.0
|
||||
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase, 결정 필요 체크리스트 기반 구현 잠금이 있는 순번 없는 Milestone 문서, 활성 Milestone 창을 처음 생성하는 공통 스킬
|
||||
---
|
||||
|
||||
# 로드맵 생성
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-ops/roadmap/` 하위에 전체 목표 / Phase / Milestone 기반 한국어 로드맵 구조를 처음 생성한다.
|
||||
전체 로드맵은 로드맵 설계와 갱신 때만 읽고, 일반 작업에서는 `current.md`의 활성 Milestone 창과 관련 Milestone 문서만 읽도록 공통 로드맵 룰을 따른다.
|
||||
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서로 시작한다.
|
||||
새 Milestone의 `구현 잠금`은 사용자만 결정할 수 있는 항목이 있을 때만 잠금으로 둔다. 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 정할 수 있는 항목은 `결정 필요`가 아니라 필요 시 표준선으로 기록한다.
|
||||
Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 해제 상태로 둔다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 프로젝트에 파일 기반 로드맵을 처음 만들 때
|
||||
- 사용자가 "로드맵 만들어줘", "마일스톤 설계해줘", "goal/phase 구조 잡아줘"라고 요청할 때
|
||||
- AI-first 개인/소규모 개발 프로젝트의 현재 방향성과 작업 기준을 구조화해야 할 때
|
||||
- 기존 README나 메모에 흩어진 계획을 `agent-ops/roadmap/` 구조로 분리할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `overall-goal`: 프로젝트 전체 목표 한 줄 또는 짧은 문단 (선택, 없으면 README와 현재 구조에서 추론)
|
||||
- `phase-hints`: 예상 Phase 목록 또는 단계 힌트 (선택)
|
||||
- `milestone-hints`: 예상 Milestone 목록 또는 기능 힌트 (선택)
|
||||
- `active-milestones`: 현재 열어둘 Milestone 목록 (선택, 없으면 현재 구현 상태와 요청에서 추론)
|
||||
|
||||
## 생성 구조
|
||||
|
||||
```text
|
||||
agent-ops/
|
||||
roadmap/
|
||||
ROADMAP.md
|
||||
current.md
|
||||
milestones/
|
||||
<milestone-slug>.md
|
||||
archive/
|
||||
YYYY/MM/<milestone-slug>.md # 아카이빙 시 생성
|
||||
```
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `agent-ops/roadmap/ROADMAP.md` | 전체 목표, Phase 흐름, 문서 순서 기반 Milestone 목록. 로드맵 생성/갱신/Phase 전환 때만 읽는다 |
|
||||
| `agent-ops/roadmap/current.md` | 지금 열려 있는 활성 Milestone 창과 선택 규칙을 담는 얇은 포인터 |
|
||||
| `agent-ops/roadmap/milestones/<milestone-slug>.md` | 일반 작업 시 읽는 Milestone 단위 목표, 구현 잠금, 범위, capability 체크리스트, 완료 기준, 범위 제외 항목 |
|
||||
| `agent-ops/roadmap/archive/YYYY/MM/<milestone-slug>.md` | 완료 또는 폐기되어 현재 후보에서 제외한 과거 Milestone. 사용자가 명시적으로 요청한 경우에만 읽는다 |
|
||||
|
||||
## 로드맵 문서 템플릿
|
||||
|
||||
- `agent-ops/roadmap/ROADMAP.md`는 `agent-ops/skills/common/_templates/roadmap-template.md` 형식을 따른다.
|
||||
- `agent-ops/roadmap/current.md`는 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식을 따른다.
|
||||
- `ROADMAP.md`는 전체 목표, Phase 흐름, Milestone 목록, 아카이브 Milestone 요약, 로딩 정책만 담고, 상세 작업 체크리스트를 넣지 않는다.
|
||||
- `current.md`는 활성 Milestone 후보 목록과 선택 규칙만 담고, 개인별 현재 작업 위치나 완료 상태를 적지 않는다.
|
||||
- 아카이브된 과거 Milestone은 `ROADMAP.md`의 `아카이브 Milestone 요약`에 당시 요약만 남기며, 아카이브 문서 자체는 일반 컨텍스트로 읽지 않는다.
|
||||
|
||||
## Milestone 문서 템플릿
|
||||
|
||||
- 새 Milestone 문서는 `agent-ops/skills/common/_templates/roadmap-milestone-template.md` 형식을 따른다.
|
||||
- 섹션 순서는 `목표`, `단계`, `상태`, `구현 잠금`, `범위`, `필수 기능`, `완료 기준`, `범위 제외`, `작업 컨텍스트`를 유지한다.
|
||||
- 새 Milestone은 제품 방향, 범위, 우선순위, 책임 경계 등 사용자만 결정할 수 있는 항목이 남아 있으면 `구현 잠금` 상태를 `잠금`으로 둔다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.
|
||||
- `구현 잠금`에는 상태와 `결정 필요` 체크리스트만 적는다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적고, 별도 해제 근거/금지 목록을 만들지 않는다.
|
||||
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 처리 가능한 내용은 `결정 필요`에 넣지 않고, 필요할 때만 `작업 컨텍스트`의 `표준선`에 기록한다.
|
||||
- `필수 기능`은 구현 파일/함수 단위 작업 목록이 아니라 Milestone에서 달성해야 할 capability 또는 산출물 체크리스트로 작성한다. 완료 근거가 명확한 항목만 `- [x]`로 표시한다.
|
||||
- `필수 기능`의 각 체크리스트 항목은 `- [ ] [item-id] 설명` 형식을 사용한다. item-id는 사람이 타이핑하고 LLM이 참조하기 쉬운 공백 없는 짧은 ASCII 토큰으로 작성한다.
|
||||
- item-id는 영문/숫자 segment 1~4개로 작성하고, segment 구분자는 `-`, `_`, `+`, `=`만 사용한다. 가능하면 1~3 segment를 우선하며, 전체 길이는 32자 이하를 권장한다.
|
||||
- item-id의 유일성 범위는 해당 Milestone 문서 안으로 제한하며, 다른 Milestone에서는 같은 item-id를 다시 사용할 수 있다. 소문자 영문 중심의 의미 있는 단어를 우선하고, 숫자나 기호는 구분이나 충돌 방지가 필요할 때만 사용한다.
|
||||
- `필수 기능`의 하위 작업은 구현 세부가 아니라 capability를 판단하는 제품/운영/문서 수준의 확인 항목으로 제한한다.
|
||||
- `완료 기준`은 검증 가능한 조건의 체크리스트로 작성한다.
|
||||
- `범위`, `범위 제외`, `작업 컨텍스트`는 설명 목록으로 작성하고, 실행해야 할 작업을 이 섹션에 숨기지 않는다.
|
||||
|
||||
## 작성 언어
|
||||
|
||||
- `agent-ops/roadmap/` 하위 로드맵 문서는 사람이 함께 검토하고 수정하는 협업 문서이므로 기본 작성 언어를 한국어로 한다.
|
||||
- 전체 구성, 섹션 제목, 설명 문장, 기능 설명, 완료 기준, TODO, 가정은 한국어 문장으로 작성한다.
|
||||
- Goal, Phase, Milestone, Scope, API, CLI처럼 개발자에게 자연스러운 일반 용어, 파일명, 경로, slug, 코드 식별자는 영어 또는 숫자를 유지할 수 있다.
|
||||
- 상태 값은 `계획`, `진행 중`, `완료`, `보류`, `폐기` 중 하나만 사용한다.
|
||||
- 프로젝트 규칙에 별도 문서 언어가 명시되어 있으면 그 규칙을 우선하되, 명시가 없으면 한국어를 기본값으로 삼는다.
|
||||
|
||||
## 순서 정책
|
||||
|
||||
- Phase와 Milestone 이름에 `1`, `2`, `M01`, `P1` 같은 순번을 붙이지 않는다.
|
||||
- 진행 순서는 `ROADMAP.md`에 적힌 위에서 아래 순서로만 해석한다.
|
||||
- Milestone 파일명은 순번 없이 `agent-ops/roadmap/milestones/<milestone-slug>.md`로 만든다.
|
||||
- 중간에 Phase나 Milestone을 끼워 넣을 수 있도록 기존 항목의 이름과 파일명을 불필요하게 바꾸지 않는다.
|
||||
|
||||
### current.md 형식
|
||||
|
||||
`agent-ops/roadmap/current.md`는 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식을 유지한다.
|
||||
|
||||
`current.md`는 개인별 작업 위치가 아니라 현재 열어둘 Milestone 후보 목록이다. 실제 현 작업 지점과 남은 작업은 `analyze-roadmap-position` 스킬이 코드와 git 상태를 함께 읽고 분석한다.
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/roadmap/ROADMAP.md` 또는 `agent-ops/roadmap/current.md`가 이미 존재하는지 확인
|
||||
- [ ] 이미 존재하면 덮어쓰지 말고 `update-roadmap` 스킬 사용을 안내
|
||||
- [ ] `README.md`, `agent-ops/GUIDE.md`, `agent-ops/rules/project/rules.md` 등 프로젝트 방향을 설명하는 문서를 확인
|
||||
- [ ] `rg --files`로 현재 프로젝트의 주요 구조를 가볍게 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-template.md`를 읽어 최신 ROADMAP 형식 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-current-template.md`를 읽어 최신 current.md 형식 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-milestone-template.md`를 읽어 최신 Milestone 형식 확인
|
||||
- [ ] `agent-ops/rules/common/rules.md`가 로드맵 디렉터리 존재 시 `agent-ops/rules/common/rules-roadmap.md`를 읽도록 라우팅하는지 확인
|
||||
- [ ] `agent-ops/rules/common/rules-roadmap.md`가 없으면 로드맵 룰이 설치되지 않은 상태로 보고하고, 프로젝트 전용 규칙에 마일스톤 컨텍스트 로딩 섹션을 추가하지 않는다
|
||||
- [ ] 각 Milestone에 사용자만 결정할 수 있는 제품 방향, 범위, 우선순위, 책임 경계가 남아 있는지 확인. 없으면 새 Milestone도 해제로 둔다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **기존 로드맵 확인**
|
||||
- `agent-ops/roadmap/` 하위 기존 파일 존재 여부를 확인한다.
|
||||
- 기존 로드맵이 있으면 새로 만들지 않고 `update-roadmap`을 사용하도록 안내한다.
|
||||
- 일부 파일만 있으면 누락 파일을 보완할지, 기존 구조를 유지할지 사용자에게 짧게 확인한다.
|
||||
|
||||
2. **프로젝트 방향 분석**
|
||||
- README와 프로젝트 규칙에서 대상 사용자, 해결하려는 문제, 현재 구현 상태를 파악한다.
|
||||
- 전체 코드를 정독하지 않는다. 로드맵 설계에 필요한 문서와 상위 구조만 확인한다.
|
||||
- 불확실한 제품 방향은 단정하지 않고 "가정" 또는 `<!-- TODO: 확인 필요 -->`로 남긴다.
|
||||
|
||||
3. **목표 / Phase / Milestone 설계**
|
||||
- 전체 목표는 프로젝트가 궁극적으로 만들려는 결과를 1~3문장으로 작성한다.
|
||||
- Phase는 큰 진화 단위로 나누고, 각 Phase에 목표를 둔다.
|
||||
- Milestone은 Phase 안에서 완료 판단이 가능한 단위로 나눈다.
|
||||
- Milestone은 기본적으로 구현 계획이 아니라 방향성과 완료 판단 기준을 공유하는 문서로 작성한다.
|
||||
- package, 함수, DB schema, API 필드, 파일 구조 같은 구현 세부는 사용자가 별도 상세 설계를 요청하기 전까지 Milestone에 확정하지 않는다.
|
||||
- 사용자만 결정할 수 있는 항목은 구현 세부로 확정하지 말고 `구현 잠금`의 `결정 필요` 체크리스트로 남긴다.
|
||||
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 정할 수 있는 항목은 표준선으로 기록하고 사용자 결정 항목으로 올리지 않는다.
|
||||
- Phase와 Milestone은 순번 없이 이름으로만 작성하고, 순서는 문서의 위에서 아래 흐름으로 표현한다.
|
||||
- 상태 값은 `계획`, `진행 중`, `완료`, `보류`, `폐기` 중 하나만 사용한다.
|
||||
|
||||
4. **로드맵 파일 생성**
|
||||
- `agent-ops/roadmap/ROADMAP.md`는 `roadmap-template.md`의 섹션 순서와 형식을 따른다.
|
||||
- `agent-ops/roadmap/current.md`는 `roadmap-current-template.md`의 섹션 순서와 형식을 따른다.
|
||||
- `ROADMAP.md`에는 전체 목표, Phase 흐름, Milestone 목록, 아카이브 Milestone 요약, 로딩 정책을 작성하고, 상세 작업 체크리스트는 Milestone 문서에 둔다.
|
||||
- `current.md`에는 활성 Milestone 목록과 선택 규칙만 작성하고, 개인별 현재 작업 위치나 완료 상태는 적지 않는다.
|
||||
- 새 로드맵의 `아카이브 Milestone 요약`은 아카이브된 항목이 없으면 `- 없음`으로 둔다.
|
||||
- 각 Milestone 문서는 `roadmap-milestone-template.md`의 섹션 순서와 형식을 따른다.
|
||||
- 각 Milestone 문서에 `구현 잠금` 섹션을 포함한다.
|
||||
- 사용자만 결정할 수 있는 항목이 있으면 `구현 잠금` 상태는 `잠금`으로 작성하고, 필요한 결정을 체크리스트로 적는다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없으면 `구현 잠금` 상태를 `해제`로 작성하고, `결정 필요`는 `없음`으로 둔다.
|
||||
- `필수 기능`과 그 하위 항목은 capability 또는 산출물 수준의 `- [ ] [item-id] 설명` 체크리스트로 작성한다.
|
||||
- 완료 근거가 확인된 항목만 `- [x]`로 표시하고, 근거가 없으면 체크하지 않는다.
|
||||
- `완료 기준`도 검증 가능한 조건의 `- [ ]` 체크리스트로 작성한다.
|
||||
- 미래 Milestone은 확정된 방향과 capability만 `필수 기능`에 넣는다. 사용자만 결정할 수 있는 불확실성은 `구현 잠금`의 `결정 필요` 체크리스트에 두고, 표준선이나 단순 조사/참고 TODO는 `작업 컨텍스트`에 둔다.
|
||||
|
||||
5. **로드맵 룰 라우팅 확인**
|
||||
- `agent-ops/rules/common/rules.md`는 `agent-ops/roadmap/` 디렉터리가 있을 때만 `agent-ops/rules/common/rules-roadmap.md`를 읽도록 라우팅해야 한다.
|
||||
- `agent-ops/rules/common/rules-roadmap.md`에는 `current.md` 의미, Milestone 선택, `ROADMAP.md` 로딩 조건, 구현 잠금, 현재 작업 지점 확인 방법이 들어 있어야 한다.
|
||||
- 로드맵 컨텍스트 로딩 규칙은 공통 로드맵 룰에 둔다. `agent-ops/rules/project/rules.md`에는 프로젝트 고유 구조, 도메인 매핑, 기술 스택만 남기고 마일스톤 컨텍스트 로딩 섹션을 추가하지 않는다.
|
||||
- 공통 로드맵 룰이 설치되지 않은 프로젝트에서는 타겟 프로젝트의 공통 파일을 임의 수정하지 말고 agent-ops 업데이트 필요 항목으로 보고한다.
|
||||
|
||||
6. **결과 보고**
|
||||
- 생성한 로드맵 파일 목록
|
||||
- 활성 Milestone 목록
|
||||
- 공통 로드맵 룰 라우팅 확인 여부
|
||||
- 확인이 필요한 TODO 또는 가정
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-ops/roadmap/ROADMAP.md`가 생성되었는가
|
||||
- [ ] `agent-ops/roadmap/current.md`가 활성 Milestone 문서 경로를 정확히 가리키는가
|
||||
- [ ] `ROADMAP.md`가 `roadmap-template.md`의 섹션 순서와 형식을 따르는가
|
||||
- [ ] `current.md`가 `roadmap-current-template.md`의 섹션 순서와 형식을 따르는가
|
||||
- [ ] `agent-ops/roadmap/milestones/` 하위에 순번 없는 Milestone 문서가 생성되었는가
|
||||
- [ ] `ROADMAP.md`에 `아카이브 Milestone 요약` 섹션이 있고, 아카이브된 항목이 없으면 `- 없음`으로 표시했는가
|
||||
- [ ] 각 Milestone 문서가 `roadmap-milestone-template.md`의 섹션 순서와 형식을 따르는가
|
||||
- [ ] 각 Milestone 문서에 `구현 잠금` 섹션이 있고, 사용자만 결정할 수 있는 항목만 잠금 상태인가
|
||||
- [ ] 잠금 상태인 Milestone의 `구현 잠금` 섹션에 `결정 필요` 체크리스트가 있는가
|
||||
- [ ] 각 Milestone 문서의 `필수 기능`과 `완료 기준`이 체크리스트 형식인가
|
||||
- [ ] 각 Milestone 문서의 `필수 기능` 체크리스트 항목이 `- [ ] [item-id] 설명` 형식이고 item-id가 해당 Milestone 안에서 유일한가
|
||||
- [ ] `ROADMAP.md`에 전체 로드맵을 일반 작업마다 읽지 말라는 로딩 정책이 포함되었는가
|
||||
- [ ] 로딩 정책에 `agent-ops/roadmap/archive/**`를 명시 요청 없이 읽지 않는다는 규칙이 포함되었는가
|
||||
- [ ] 로딩 정책에 `구현 잠금`이 없거나 잠긴 Milestone의 현재 요청과 직접 관련된 `결정 필요` 체크리스트 확인 규칙이 포함되었는가
|
||||
- [ ] `agent-ops/rules/common/rules.md`가 로드맵 디렉터리 존재 시 `rules-roadmap.md`를 읽도록 라우팅하는가
|
||||
- [ ] `agent-ops/rules/common/rules-roadmap.md`가 로드맵 컨텍스트 로딩과 구현 잠금 규칙을 포함하는가
|
||||
- 검증 실패 시: 누락된 파일이나 섹션만 보완하고 기존 내용을 덮어쓰지 않는다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## 생성 완료
|
||||
|
||||
- 로드맵: agent-ops/roadmap/ROADMAP.md
|
||||
- 현재 컨텍스트: agent-ops/roadmap/current.md
|
||||
- Milestone 문서: <N개>
|
||||
- 활성 Milestone: <N개>
|
||||
- 구현 잠금: <잠금 Milestone N개 | 해제 Milestone N개>
|
||||
- 공통 로드맵 룰: <확인함 | 설치 필요 | 해당 없음>
|
||||
|
||||
## 활성 Milestone
|
||||
|
||||
- <milestone-name>: agent-ops/roadmap/milestones/<milestone-slug>.md
|
||||
|
||||
## TODO 항목
|
||||
|
||||
- <확인이 필요한 가정 또는 미정 항목> (해당 시)
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 기존 `agent-ops/roadmap/` 파일을 덮어쓰지 않는다.
|
||||
- 일반 작업마다 전체 `ROADMAP.md`를 읽도록 규칙을 만들지 않는다.
|
||||
- `current.md`에 `agent-ops/roadmap/archive/**` 경로를 넣지 않는다.
|
||||
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
|
||||
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 넣지 않는다.
|
||||
- `current.md`에 개인별 현재 작업 위치나 완료 상태를 적지 않는다.
|
||||
- Milestone 문서를 단순 TODO 목록으로만 만들지 않는다. 반드시 템플릿의 목표, 단계, 상태, 구현 잠금, 범위, 필수 기능, 완료 기준, 범위 제외, 작업 컨텍스트를 포함한다.
|
||||
- Milestone 문서에서 `구현 잠금` 섹션을 생략하지 않는다.
|
||||
- 사용자만 결정할 수 있는 항목이 남아 있는데 새 Milestone을 `해제` 상태로 만들지 않는다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없는 Milestone을 관성적으로 `잠금` 상태로 만들지 않는다.
|
||||
- Milestone을 구현 계획처럼 package/file/function 단위로 과도하게 세분화하지 않는다.
|
||||
- 해야 할 capability 또는 산출물을 일반 불릿이나 설명 문장에 숨기지 않는다. `필수 기능` 또는 그 하위 항목의 item-id가 있는 체크리스트로 작성한다.
|
||||
- 확정되지 않은 제품 방향을 사실처럼 단정하지 않는다.
|
||||
- `agent-ops/rules/common/`이나 `agent-ops/skills/common/`을 타겟 프로젝트에서 직접 수정하지 않는다.
|
||||
95
agent-ops/skills/common/create-skill/SKILL.md
Normal file
95
agent-ops/skills/common/create-skill/SKILL.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
name: create-skill
|
||||
version: 1.0.0
|
||||
description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
|
||||
---
|
||||
|
||||
# Create Skill
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-ops/skills/` 하위에 올바른 형식의 SKILL.md 파일을 생성한다.
|
||||
기존 skill-template.md 를 기반으로, 요청 목적에 맞는 내용을 채워 넣는다.
|
||||
생성 후 라우팅 항목을 추가한다.
|
||||
|
||||
### 생성 위치 결정
|
||||
- `.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/rules/common/rules.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` 형식을 따른다
|
||||
- 프로젝트 특화 내용보다 범용 절차를 우선한다
|
||||
- 절차는 구체적이되 지나치게 세부 구현을 기술하지 않는다
|
||||
|
||||
4. **라우팅 업데이트**
|
||||
- `.agent-ops-source` 마커가 **있으면** (공통 관리 레포): `agent-ops/rules/common/rules.md`에 라우팅 항목 추가
|
||||
- `.agent-ops-source` 마커가 **없으면** (타겟 프로젝트): `agent-ops/rules/project/rules.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, version, description이 올바르게 기재되었는가
|
||||
- [ ] 라우팅 대상 파일에 해당 스킬의 라우팅 항목이 추가되었는가
|
||||
- 검증 실패 시: 누락된 섹션 또는 라우팅 항목을 사용자에게 알리고 해당 부분만 보완한다
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 이미 존재하는 skill 을 덮어쓰지 않는다
|
||||
- 프로젝트 특화 경로(예: `app/screens/`)를 skill 본문에 하드코딩하지 않는다
|
||||
- skill 생성과 무관한 코드 파일을 수정하지 않는다
|
||||
- 라우팅 대상 파일의 기존 항목을 삭제하거나 재정렬하지 않는다
|
||||
- 하나의 skill 에 여러 독립적인 책임을 묶지 않는다
|
||||
249
agent-ops/skills/common/init-agent-ops/SKILL.md
Normal file
249
agent-ops/skills/common/init-agent-ops/SKILL.md
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
---
|
||||
name: init-agent-ops
|
||||
version: 1.1.2
|
||||
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. 초기 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` 등)이 있는지 확인
|
||||
|
||||
## 핵심 원칙
|
||||
|
||||
- 기존 구조를 우선한다.
|
||||
- 새 파일 생성은 꼭 필요한 최소 범위로 제한한다.
|
||||
- 도메인은 발명하지 말고 현재 구조에서 발견한다.
|
||||
- 처음에는 핵심 도메인만 생성한다.
|
||||
- 반복되는 작업만 초기 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 추적 제외 |
|
||||
| `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore` | `agent-task/archive/**`, `agent-ops/roadmap/archive/**` 한 줄씩 추가 |
|
||||
| `.claude/settings.json`, `opencode.json` | 파일이 없으면 `agent-task/archive/**`, `agent-ops/roadmap/archive/**` 읽기/검색 제외 설정 생성, 있으면 구조적으로 병합하고 병합할 수 없을 때 수동 병합 안내 |
|
||||
|
||||
에이전트별 파일명:
|
||||
|
||||
실제 생성/동기화 대상 목록은 `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 스캐폴드를 생성한다.
|
||||
|
||||
```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-task/archive/**`와 `agent-ops/roadmap/archive/**`를 추가한다
|
||||
- `.claude/settings.json`, `opencode.json`이 없으면 archive 읽기/검색 제외 설정을 생성하고, 있으면 가능한 경우 기존 설정을 보존하며 필요한 제외 설정만 병합한다
|
||||
- 대상 루트에 `.agent-ops-source`가 있으면 AI ignore / permission 파일은 보강하지 않는다
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**` 제외는 `.gitignore`에 추가하지 않는다
|
||||
|
||||
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. **초기 skill 제안**
|
||||
- 신규 프로젝트: 최소 2개만 제안한다
|
||||
- 운영중 프로젝트: 반복 작업 기반으로 필요한 skill을 제안한다
|
||||
|
||||
8. **결과 보고**
|
||||
- 상태 판별 결과, 생성된 파일 목록, 도메인 제안, 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/` 항목이 추가되어 있는가
|
||||
- [ ] `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`가 포함되어 있는가
|
||||
- [ ] `.claude/settings.json`, `opencode.json`에 `agent-task/archive/**`와 `agent-ops/roadmap/archive/**` 제외 설정이 있거나, 병합 불가 시 수동 병합 안내를 출력했는가
|
||||
- [ ] `.gitignore`에 `agent-task/archive/**` 또는 `agent-ops/roadmap/archive/**`를 추가하지 않았는가
|
||||
- 검증 실패 시: 누락된 파일/항목을 사용자에게 알리고 해당 부분만 보완한다
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 진입 파일에 rules/common/rules.md 외 내용을 추가하지 않는다.
|
||||
- `agent-task/archive/**`와 `agent-ops/roadmap/archive/**` 제외를 `.gitignore`에 추가하지 않는다.
|
||||
- 실제 구조보다 앞선 추상 구조를 강요하지 않는다.
|
||||
- 처음부터 많은 domain / skill을 만들지 않는다.
|
||||
- rules/common/rules.md를 프로젝트에서 직접 수정하지 않는다.
|
||||
- rules/project/rules.md에 rules/common/rules.md와 중복되는 내용을 넣지 않는다.
|
||||
371
agent-ops/skills/common/plan/SKILL.md
Normal file
371
agent-ops/skills/common/plan/SKILL.md
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
---
|
||||
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. A separate implementing agent, or the same agent in an implementation pass, reads the plan file and does the coding. The code-review skill archives both files after review and moves PASS tasks under agent-task/archive/YYYY/MM/.
|
||||
---
|
||||
|
||||
# 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
|
||||
code-review skill -> verdict + archive, complete.log, and PASS task-directory archive move or new follow-up plan/review files
|
||||
```
|
||||
|
||||
## 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/`, using a short snake_case name such as `refactoring`.
|
||||
- `{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.
|
||||
- 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.
|
||||
|
||||
Task directory naming rules:
|
||||
|
||||
- A single-plan task uses `agent-task/{task_group}/` with a short snake_case category name, e.g. `agent-task/refactoring/`.
|
||||
- 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.
|
||||
- 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 defaults to `local` when the plan is explicit, tests are runnable, and failure is review-detectable.
|
||||
- Use `cloud` for weak tests, broad API/call-site impact, ambiguity, storage/concurrency/protocol/auth risk, or prior local failure.
|
||||
- Use `cloud-G07` or higher for terminal-agent work: shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, or terminal benchmark-style tasks. Merely running deterministic tests such as `go test` does not make a task terminal-agent work.
|
||||
- Use `cloud-G07` or higher when acceptance depends on a real interactive external tool, TUI, PTY, browser, screen repaint/cursor stream, or bin-level smoke output. This is mandatory when unit tests pass but the real smoke/integration command fails.
|
||||
- Use `cloud-G07` or higher when a prior review found verification trust failure, reconstructed command output, or claimed stdout/stderr that does not match a rerun.
|
||||
- Keep high-risk design judgment on `cloud` with a higher grade; the runtime may map `cloud-GNN` to frontier-class models.
|
||||
- Review may be `local` for narrow/low-risk checks and `cloud` for multi-file/API/test-meaning reviews, security/auth, storage/migration, concurrency, protocol/schema, cross-domain, or repeated Required issues.
|
||||
- Raise `GNN` with scope, ambiguity, missing tests, irreversible behavior, and blast radius; 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` + filled `CODE_REVIEW-*-G??.md` | Ready for code-review skill |
|
||||
| `complete.log` + `*.log` files | Task complete (PASS), before final task-directory archive move |
|
||||
| `agent-task/archive/YYYY/MM/{task_name}/complete.log` + `*.log` files | Archived completed task path (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`
|
||||
|
||||
| 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.
|
||||
|
||||
로드맵 확인:
|
||||
|
||||
- `agent-ops/roadmap/current.md`가 있으면 구현 계획 파일을 만들기 전에 읽고, 사용자 요청, 브랜치, 변경 경로를 기준으로 관련 Milestone을 선택한다.
|
||||
- `current.md`가 `agent-ops/roadmap/archive/**`를 가리키면 해당 문서는 읽지 말고 활성 Milestone이 아니라고 보고한다.
|
||||
- 선택한 Milestone을 한 번 읽는다. `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인하고, 그 결정 없이는 `PLAN-*-G??.md`, `CODE_REVIEW-*-G??.md`, file/API/package 수준 구현 단계를 확정하지 않는다.
|
||||
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조, 도메인 rule, 플랫폼 관례로 정할 수 있는 세부는 표준선/가정으로 계획에 기록하고 진행할 수 있다.
|
||||
- 사용자가 선택한 Milestone의 작업, 구현, 계획 작성을 명시했고 현재 계획에 필요한 결정이 모두 정해져 있다면 계획 작성을 이어간다. Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 roadmap update 흐름으로 `구현 잠금` 상태를 `해제`로 갱신한다. 현재 요청에 직접 걸리는 결정이 필요하면 그 항목만 체크리스트로 남기고 사용자에게 확인한다.
|
||||
- roadmap/current 파일이 없으면 기존 task routing 규칙대로 진행한다.
|
||||
|
||||
Use short snake_case task group names, 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 any files. Work through them in order; do not proceed to the next step until every checkbox is done.
|
||||
|
||||
- [ ] **Read all source files in full** — read every source file the change will touch, whole file. No partial reads.
|
||||
- [ ] **Read all test files in full** — read every test file that exercises the changed behavior.
|
||||
- [ ] **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.
|
||||
- [ ] **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, and call-site count.
|
||||
- [ ] **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** — use `local` if the plan is explicit and tests are sufficient; use `cloud` if any of the following apply:
|
||||
- Tests are weak or do not cover the changed behavior
|
||||
- Broad API/call-site impact
|
||||
- Concurrency, storage, protocol, or auth risk
|
||||
- Prior local build failure on this task
|
||||
- Terminal-agent work: shell/CLI workflow implementation, bin script orchestration, process control, stdout/stderr parsing, exit-status contracts, long-running command diagnosis, or terminal benchmark-style tasks
|
||||
- Real bin/smoke/integration verification failed after unit tests passed
|
||||
- Interactive TUI/PTY/browser/external CLI automation or screen-rendered output is part of the success condition
|
||||
- A prior review marked verification trust Fail/Warn because recorded command output did not match a rerun
|
||||
- [ ] **Decide GNN** — assign a higher grade as scope, ambiguity, irreversibility, and blast radius increase. Grade is complexity-based, not model-name-based.
|
||||
|
||||
## Step 4 - Archive Existing Active Files
|
||||
|
||||
Before writing new active files for the chosen active task directory:
|
||||
|
||||
- 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`.
|
||||
|
||||
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.
|
||||
- `배경`: 2-4 sentences explaining why the work is needed.
|
||||
- `분석 결과`: 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 and test file read during analysis, with path.
|
||||
- `테스트 커버리지 공백`: 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.
|
||||
- `범위 결정 근거`: 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 plan item, one item for all intermediate/final verification, 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. 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.
|
||||
|
||||
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 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.
|
||||
|
||||
```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.
|
||||
> 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}
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[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이면 다음 active plan/review 파일을 즉시 작성한다.
|
||||
4. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.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`로 아카이브한다.
|
||||
- [ ] 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 split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
{pre-filled from plan — one bullet per review focus area}
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
|
||||
### {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) |
|
||||
| 구현 항목별 완료 여부 (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 |
|
||||
| 리뷰어를 위한 체크포인트 | 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}/`.
|
||||
- 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`.
|
||||
- Both first lines match `<!-- task={task_name} plan={N} tag={TAG} -->`.
|
||||
- Previous active files, if any, were archived with correct numeric suffixes.
|
||||
- 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 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."
|
||||
17
agent-ops/skills/common/router.md
Normal file
17
agent-ops/skills/common/router.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# 공통 스킬 라우터
|
||||
|
||||
| 요청 키워드 | 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` |
|
||||
| README 작성해줘, README 만들어줘, 프로젝트 설명 문서 만들어줘 | `agent-ops/skills/common/create-readme/SKILL.md` |
|
||||
| 로드맵 만들어줘, roadmap 생성, 마일스톤 설계, goal/phase 구조 잡아줘 | `agent-ops/skills/common/create-roadmap/SKILL.md` |
|
||||
| 로드맵 업데이트, roadmap 갱신, 마일스톤 갱신, 마일스톤 아카이브, phase 변경, 현재 마일스톤 변경, 로드맵 한국어 전환, 로드맵 번역 | `agent-ops/skills/common/update-roadmap/SKILL.md` |
|
||||
| 지금 작업이 뭐지?, 현재 작업 분석, 어디까지 했지?, 남은 작업 뭐야 | `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` |
|
||||
38
agent-ops/skills/common/sync-pull/SKILL.md
Normal file
38
agent-ops/skills/common/sync-pull/SKILL.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
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를 내려받는다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- "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`와 일치하는가
|
||||
- [ ] `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`가 포함되어 있는가
|
||||
- [ ] agentic-framework의 AI ignore / permission 파일은 수정되거나 stage되지 않았는가
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- sync.sh 를 거치지 않고 직접 파일을 복사하지 않는다
|
||||
80
agent-ops/skills/common/sync-push/SKILL.md
Normal file
80
agent-ops/skills/common/sync-push/SKILL.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
name: sync-push
|
||||
description: 현재 프로젝트의 agent-ops를 agentic-framework로 올리거나, agentic-framework의 공통 agent-ops를 대상 프로젝트 또는 상위 폴더의 agent-ops 적용 프로젝트 전체로 push하고 푸시한다. "agent-ops 싱크해", "agent-ops 동기화해", "agentic-framework에 올려줘" 요청 시 사용한다.
|
||||
---
|
||||
|
||||
# sync-push
|
||||
|
||||
## 목적
|
||||
|
||||
`agent-ops/bin/sync.sh`를 호출해 agent-ops 공통 파일을 push 방향으로 동기화한다.
|
||||
|
||||
- 일반 프로젝트에서는 현재 프로젝트 → agentic-framework 방향으로 올린다.
|
||||
- agentic-framework 원본 프로젝트에서는 agentic-framework → 대상 프로젝트 방향으로 보내고, 대상 repo를 commit/push 한다.
|
||||
- agentic-framework 원본 프로젝트에서 대상이 명시되지 않으면 현재 프로젝트의 상위 폴더에 있는 agent-ops 적용 프로젝트 전체로 보낸다.
|
||||
|
||||
## 버전 정책
|
||||
|
||||
- `agentic-framework` 원본 프로젝트에서 대상 프로젝트로 전파하는 push 동기화는 버전을 올리지 않는다.
|
||||
- 이 경우 현재 `agentic-framework`의 `agent-ops/.version` 값을 그대로 대상 repo에 전파한다.
|
||||
- 일반 프로젝트에서 `agentic-framework`로 공통 변경을 올리는 push 동기화는 기존처럼 `sync.sh`가 버전을 한 단계 올린다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- "agent-ops 싱크해", "agent-ops 동기화해" 요청 시
|
||||
- "agentic-framework에 올려줘" 요청 시
|
||||
- "agent-ops를 [프로젝트]로 싱크해" 요청 시
|
||||
|
||||
## 실행 절차
|
||||
|
||||
### 현 프로젝트가 일반 프로젝트인 경우 (`.agent-ops-source` 없음)
|
||||
|
||||
1. 현재 프로젝트의 **상위 폴더(`../`)** 에 `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`가 버전을 한 단계 올리고 현재 프로젝트와 `agentic-framework`에 같은 버전을 반영한다
|
||||
6. 일반 프로젝트에서 agentic-framework로 올릴 때는 AI ignore / permission 파일을 보강하거나 stage하지 않는다
|
||||
|
||||
### 현 프로젝트가 agentic-framework인 경우 (`.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`는 현재 agentic-framework의 `agent-ops/rules/common/rules.md` 내용을 대상 프로젝트 루트의 진입 파일에 덮어쓴다
|
||||
6. 적용 후 각 대상 repo에서 agent-ops 공통 관리 경로(`rules/common/rules.md` 포함), 진입 파일, AI ignore / permission 파일을 stage 하여 commit/push 한다
|
||||
7. AI ignore / permission 파일은 대상 프로젝트의 기존 내용을 덮어쓰지 않고, 누락된 표준 archive 제외 설정만 보강한다
|
||||
8. 이 과정에서는 버전을 새로 올리지 않고 현재 agentic-framework의 `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` 내용으로 교체한다.
|
||||
|
||||
```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`의 진입 파일로 제한한다. AI ignore / permission 파일은 framework에서 일반 프로젝트로 내려보내는 경우에만 대상 repo에서 추가 stage한다.
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] sync.sh 가 오류 없이 완료됐는가
|
||||
- [ ] 버전 충돌 경고가 없었는가 — 있었다면 사용자에게 수동 머지 필요함을 알린다
|
||||
- [ ] 대상 repo의 `agent-ops/rules/common/rules.md`가 현재 agentic-framework의 `agent-ops/rules/common/rules.md`와 일치하는가
|
||||
- [ ] agentic-framework에서 대상 프로젝트로 push한 경우, `agent-ops/bin/entry-files.sh`의 모든 진입 파일 내용이 현재 agentic-framework의 `agent-ops/rules/common/rules.md`와 일치하는가
|
||||
- [ ] framework에서 대상 프로젝트로 push한 경우, `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`가 포함되어 있는가
|
||||
- [ ] 일반 프로젝트에서 agentic-framework로 push한 경우, AI ignore / permission 파일이 agentic-framework에 유입되지 않았는가
|
||||
- [ ] 대상 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 파일 갱신만 담당한다
|
||||
358
agent-ops/skills/common/update-roadmap/SKILL.md
Normal file
358
agent-ops/skills/common/update-roadmap/SKILL.md
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
---
|
||||
name: update-roadmap
|
||||
version: 1.12.0
|
||||
description: 기존 전체 목표, Phase, 결정 필요 체크리스트 기반 구현 잠금이 있는 순번 없는 Milestone 기반 한국어 로드맵을 갱신하고 신규 작업 배치, current.md 동기화, 완료/폐기 Milestone 아카이빙을 처리하는 공통 스킬
|
||||
---
|
||||
|
||||
# 로드맵 업데이트
|
||||
|
||||
## 목적
|
||||
|
||||
기존 `agent-ops/roadmap/` 구조를 현재 프로젝트 방향과 진행 상태에 맞게 한국어로 갱신한다.
|
||||
로드맵 전체를 매 작업마다 읽지 않도록 유지하면서, `current.md`의 활성 Milestone 창이 실제 작업 후보 목록으로 동작하게 한다.
|
||||
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서로 유지한다.
|
||||
구현 잠금은 승인 절차가 아니라 사용자 결정이 필요한지 표시하는 얇은 상태다.
|
||||
제품 방향, 범위, 우선순위, 책임 경계처럼 사용자만 결정할 수 있는 항목이 남아 있으면 `잠금`으로 두고 `결정 필요` 체크리스트에 질문을 적는다.
|
||||
기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 필요 시 표준선으로 기록한다.
|
||||
Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||
잠금 상태 변경은 Milestone 완료 판정이 아니므로 `필수 기능`과 `완료 기준`을 자동 완료 처리하지 않는다.
|
||||
완료 또는 폐기되어 현재 작업 후보에서 제외할 과거 Milestone은 `agent-ops/roadmap/archive/YYYY/MM/`로 이동하고, `ROADMAP.md`에는 아카이빙 당시 요약만 남긴다.
|
||||
아카이브된 Milestone은 최신 스킬 규약이나 템플릿에 맞춰 재포맷하지 않고, 사용자가 명시적으로 과거 기록 확인이나 복원을 요청한 경우에만 읽는다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
- 사용자가 "로드맵 업데이트", "마일스톤 갱신", "phase 변경", "현재 활성 마일스톤 바꿔줘"라고 요청할 때
|
||||
- 사용자가 "로드맵 한국어 전환", "로드맵 번역", "영문 로드맵을 한국어로 바꿔줘"라고 요청할 때
|
||||
- Milestone 완료, 보류, 폐기, 신규 추가가 필요할 때
|
||||
- 완료 또는 폐기된 Milestone을 요약하고 archive로 이동해야 할 때
|
||||
- 특정 기능이나 작업을 새 Milestone, 기존 Milestone의 태스크, 기존 태스크 하위 항목 중 적절한 위치에 추가해야 할 때
|
||||
- 활성 Milestone 창에 포함할 Milestone 목록이 달라졌을 때
|
||||
- 기본 목표, Phase, Milestone의 목표, 범위, 필수 기능, 완료 기준이 달라졌을 때
|
||||
- `ROADMAP.md` 또는 `current.md` 형식이 템플릿과 달라 표준화해야 할 때
|
||||
- Milestone 문서 형식이 제각각이라 템플릿 기준으로 표준화해야 할 때
|
||||
- 실제 구현 상태와 로드맵 파일이 어긋난 것 같아 동기화가 필요할 때
|
||||
- 사용자가 Milestone의 방향/범위 보완, 구현 잠금 해제, 또는 잠금 상태 점검을 요청할 때
|
||||
|
||||
## 입력
|
||||
|
||||
- `mode`: `status` / `milestone` / `phase` / `replan` / `sync` / `concretize` / `archive` 중 하나 (선택, 요청에서 추론 가능)
|
||||
- `target-milestone`: 갱신할 Milestone 이름, slug, 파일 경로 (선택)
|
||||
- `active-milestones`: 활성 Milestone 창에 둘 Milestone 이름, slug, 파일 경로 목록 (선택)
|
||||
- `new-feature`: 추가할 기능, 작업, 또는 새 Milestone 설명 (선택)
|
||||
- `placement`: 새 작업 배치 위치. 예: `<anchor-milestone> 앞`, `<anchor-milestone> 뒤`, `<milestone-name> 안`, `<phase-name> 안`, `<anchor-task> 앞`, `<anchor-task> 아래`, `auto` (선택, 없으면 자동 판단)
|
||||
- `placement-unit`: 삽입 단위. `milestone` / `task` / `subtask` / `auto` 중 하나 (선택, 없으면 작업 성격으로 판단)
|
||||
- `lock-state`: Milestone 구현 잠금 상태. `잠금` / `해제` 중 하나 (선택, 없으면 기존 상태 유지 또는 결정 필요 여부로 판단)
|
||||
- `decision-needed`: `구현 잠금`에 남길 사용자만 결정할 수 있는 질문 목록 (선택)
|
||||
- `unlock-evidence`: 이전 문서 호환 입력. 새 문서에서는 별도 해제 근거 대신 필요한 사용자 결정이 남아 있는지로 상태를 판단한다 (선택)
|
||||
- `concretization-evidence`: 이전 문서 호환 입력. 새 문서에서는 `decision-needed`를 우선 사용한다 (선택)
|
||||
- `change-summary`: 반영할 방향 변경 또는 진행 상황 요약 (선택)
|
||||
- `evidence`: 완료 판단에 사용할 파일, PR, 테스트, 커밋, 사용자 설명 (선택)
|
||||
- `archive-date`: Milestone 아카이브 날짜. 없으면 현재 날짜를 사용한다 (선택)
|
||||
- `archive-summary`: `ROADMAP.md`에 남길 과거 Milestone 요약. 없으면 대상 Milestone 문서와 evidence에서 1~2문장으로 추출한다 (선택)
|
||||
|
||||
## 모드
|
||||
|
||||
| mode | 사용 상황 |
|
||||
|------|-----------|
|
||||
| `status` | 태스크 체크박스, Milestone 상태, 완료 기준만 갱신 |
|
||||
| `milestone` | Milestone 목표, 범위, 태스크 체크리스트, 완료 기준 수정 |
|
||||
| `phase` | Phase 설명 또는 활성 Milestone 창 전환 |
|
||||
| `replan` | 전체 Phase/Milestone 흐름 재구성 |
|
||||
| `sync` | 실제 프로젝트 상태와 로드맵 불일치 점검 후 보정 |
|
||||
| `concretize` | Milestone의 방향/범위를 보완하거나 결정 필요 여부에 따라 잠금 상태를 갱신 |
|
||||
| `archive` | 완료 또는 폐기된 Milestone을 요약하고 `agent-ops/roadmap/archive/YYYY/MM/`로 이동 |
|
||||
|
||||
## 작성 언어
|
||||
|
||||
- `agent-ops/roadmap/` 하위 로드맵 문서는 사람이 함께 검토하고 수정하는 협업 문서이므로 기본 작성 언어를 한국어로 한다.
|
||||
- 전체 구성, 섹션 제목, 설명 문장, 기능 설명, 완료 기준, TODO, 가정은 한국어 문장으로 작성한다.
|
||||
- Goal, Phase, Milestone, Scope, API, CLI처럼 개발자에게 자연스러운 일반 용어, 파일명, 경로, slug, 코드 식별자는 영어 또는 숫자를 유지할 수 있다.
|
||||
- 상태 값은 `계획`, `진행 중`, `완료`, `보류`, `폐기` 중 하나만 사용한다.
|
||||
- 기존 영문 상태 값은 `Planned` -> `계획`, `Active` -> `진행 중`, `Done` -> `완료`, `Paused` -> `보류`, `Dropped` -> `폐기`로 맞춘다.
|
||||
- 기존 영문 섹션명이 갱신 범위에 포함되면 아래 한국어 표준 섹션명으로 정리한다.
|
||||
- `Goal` -> `목표`
|
||||
- `Phase` -> `단계`
|
||||
- `Status` -> `상태`
|
||||
- `Implementation Lock` / `구현 구체화` -> `구현 잠금`
|
||||
- `Scope` -> `범위`
|
||||
- `Required Features` -> `필수 기능`
|
||||
- `Success Criteria` -> `완료 기준`
|
||||
- `Non-Goals` -> `범위 제외`
|
||||
- `Context for Work` -> `작업 컨텍스트`
|
||||
|
||||
## 로드맵 문서 템플릿
|
||||
|
||||
- `agent-ops/roadmap/ROADMAP.md`는 `agent-ops/skills/common/_templates/roadmap-template.md` 형식을 기준으로 생성·갱신한다.
|
||||
- `agent-ops/roadmap/current.md`는 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식을 기준으로 생성·갱신한다.
|
||||
- `ROADMAP.md` 표준 섹션은 `전체 목표`, `Phase 흐름`, `Milestone 목록`, `아카이브 Milestone 요약`, `로딩 정책`이다.
|
||||
- `ROADMAP.md`에는 Phase/Milestone 흐름, 현재 참조할 Milestone 문서 링크, 아카이브된 Milestone 요약만 두고, 상세 작업 체크리스트는 Milestone 문서에 둔다.
|
||||
- `Milestone 목록`은 현재 흐름에서 직접 참조할 아카이브되지 않은 Milestone 목록이다. 아카이브된 항목은 이 목록에서 제거하고 `아카이브 Milestone 요약`으로 옮긴다.
|
||||
- `아카이브 Milestone 요약`에는 아카이브 당시 상태, 날짜, 목표 요약, 핵심 산출물 또는 근거, 후속 영향만 짧게 남긴다. 아카이브 문서 링크나 상세 경로는 넣지 않는다.
|
||||
- `current.md` 표준 섹션은 `활성 Milestone`, `선택 규칙`이다.
|
||||
- `current.md`는 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태의 진실로 쓰지 않는다.
|
||||
- `current.md`의 활성 Milestone은 `agent-ops/roadmap/milestones/` 하위 문서만 가리키며, `agent-ops/roadmap/archive/**`는 포함하지 않는다.
|
||||
- 갱신 범위에 포함된 `ROADMAP.md`나 `current.md`가 템플릿과 다르면, 프로젝트 로드맵 정보는 보존하면서 표준 섹션 순서로 재배치한다.
|
||||
- `current.md`에 남아 있는 개인별 또는 세션별 작업 위치/완료 상태는 공유 로드맵 정보로 이관하지 말고 결과 보고의 확인 필요 항목에 남긴다.
|
||||
|
||||
## Milestone 문서 템플릿
|
||||
|
||||
- Milestone 문서는 `agent-ops/skills/common/_templates/roadmap-milestone-template.md` 형식을 기준으로 생성·갱신한다.
|
||||
- 표준 섹션 순서는 `목표`, `단계`, `상태`, `구현 잠금`, `범위`, `필수 기능`, `완료 기준`, `범위 제외`, `작업 컨텍스트`다.
|
||||
- 갱신 범위에 포함된 Milestone 문서가 제각각 형식이면, 내용을 삭제하지 말고 표준 섹션 순서로 재배치한다.
|
||||
- 기존 Milestone에 `구현 잠금` 섹션이 없으면 추가하고, 사용자만 결정할 수 있는 항목이 남아 있는지 보고 `잠금` 또는 `해제`를 정한다.
|
||||
- `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
|
||||
- `구현 잠금`은 사용자만 결정할 수 있는 항목이 있으면 `잠금`, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되면 `해제`로 둔다.
|
||||
- `구현 잠금`에는 상태와 `결정 필요` 체크리스트만 유지한다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적고, 별도 해제 근거/금지 목록은 만들지 않는다.
|
||||
- 기존 Milestone 문서에 `이유`, `해제 근거`, `잠금 중 금지`, 잠금 해제를 위한 별도 체크리스트가 있으면 사용자만 결정할 수 있는 질문만 `결정 필요` 체크리스트로 옮기고, 표준선이나 배경 설명은 `작업 컨텍스트`로 옮기거나 제거한다.
|
||||
- `필수 기능`은 구현 파일/함수 단위 작업 목록이 아니라 Milestone에서 달성해야 할 capability 또는 산출물 체크리스트로 유지한다.
|
||||
- `필수 기능`의 각 체크리스트 항목은 `- [ ] [item-id] 설명` 형식을 사용한다. item-id는 사람이 타이핑하고 LLM이 참조하기 쉬운 공백 없는 짧은 ASCII 토큰으로 작성한다.
|
||||
- item-id는 영문/숫자 segment 1~4개로 작성하고, segment 구분자는 `-`, `_`, `+`, `=`만 사용한다. 가능하면 1~3 segment를 우선하며, 전체 길이는 32자 이하를 권장한다.
|
||||
- item-id의 유일성 범위는 해당 Milestone 문서 안으로 제한하며, 다른 Milestone에서는 같은 item-id를 다시 사용할 수 있다. 기존 item-id는 사용자가 명시적으로 바꾸라고 하지 않는 한 보존하고, 새 항목에는 소문자 영문 중심의 의미 있는 id를 만든다.
|
||||
- `완료 기준`은 검증 가능한 조건의 체크리스트로 유지한다.
|
||||
- 일반 불릿이나 설명 문장에 숨어 있는 capability/산출물은 성격을 판단해 `필수 기능` 체크리스트 또는 기존 항목의 하위 체크리스트로 옮긴다.
|
||||
- `범위`, `범위 제외`, `작업 컨텍스트`는 설명 목록으로 유지하고, 실행해야 할 작업을 이 섹션에 숨기지 않는다.
|
||||
|
||||
## Milestone 아카이브 정책
|
||||
|
||||
- 활성 또는 예정 Milestone 문서는 `agent-ops/roadmap/milestones/<milestone-slug>.md`에 둔다.
|
||||
- 완료 또는 폐기되어 현재 작업 후보에서 제외할 Milestone은 `agent-ops/roadmap/archive/YYYY/MM/<milestone-slug>.md`로 이동한다.
|
||||
- 아카이브 날짜는 사용자 지정 `archive-date`, 완료 evidence 날짜, 현재 날짜 순으로 결정한다.
|
||||
- 아카이브 전 대상 Milestone 문서를 1회 읽어 `ROADMAP.md`의 `아카이브 Milestone 요약`에 남길 요약을 만든다.
|
||||
- 아카이브 요약은 `Milestone 이름`, `상태`, `아카이브일`, `요약`, `핵심 산출물/근거`, `후속 영향`만 짧게 담는다.
|
||||
- 첫 아카이브 항목을 추가할 때 `아카이브 Milestone 요약`의 `- 없음` placeholder는 제거한다.
|
||||
- 아카이브된 Milestone은 `ROADMAP.md`의 `Milestone 목록`에서 제거하고, `current.md`의 활성 Milestone에서도 제거한다.
|
||||
- `agent-ops/roadmap/archive/**`는 사용자가 과거 기록 확인, 복원, 또는 아카이브 문서 직접 수정을 명시적으로 요청한 경우에만 읽는다.
|
||||
- sync, 템플릿 표준화, 스킬 규약 업데이트는 아카이브 문서를 갱신 범위에 포함하지 않는다.
|
||||
- 아카이브 문서는 아카이빙 당시의 기록 스냅샷으로 보고, 최신 `roadmap-milestone-template.md` 형식에 맞춰 재포맷하지 않는다.
|
||||
- 아카이브 대상 경로가 이미 있으면 덮어쓰지 않고 확장자 앞에 `-1`, `-2`처럼 다음 숫자를 붙인다.
|
||||
|
||||
## 순서 정책
|
||||
|
||||
- Phase와 Milestone 이름에 `1`, `2`, `M01`, `P1` 같은 순번을 붙이지 않는다.
|
||||
- 진행 순서는 `ROADMAP.md`에 적힌 위에서 아래 순서로만 해석한다.
|
||||
- 새 Milestone 파일은 순번 없이 `agent-ops/roadmap/milestones/<milestone-slug>.md`로 만든다.
|
||||
- 중간에 Phase나 Milestone을 끼워 넣을 수 있도록 기존 항목의 이름과 파일명을 불필요하게 바꾸지 않는다.
|
||||
- 기존 프로젝트에 이미 순번 파일명이 있으면 대규모 rename을 하지 말고, 갱신 범위에 포함된 새 항목부터 순번 없는 형식을 적용한다.
|
||||
- 새 작업은 습관적으로 새 Milestone으로 만들거나 목록 맨 앞/뒤에 붙이지 않는다.
|
||||
- 사용자가 특정 Milestone 앞/뒤, 특정 Phase 안, 필수 기능 목록 내 위치, 기존 태스크 item-id, 또는 기존 태스크 앞/뒤/아래를 지정하면 목표와 범위 제외 항목에 충돌하지 않는 한 그 위치를 우선한다.
|
||||
- 사용자가 위치를 지정하지 않으면 `ROADMAP.md`의 Phase 흐름, 기존 Milestone 목표, 기존 필수 기능/태스크, 선후 의존성, 활성 Milestone 창, 완료 기준을 보고 가장 자연스러운 위치를 자동으로 판단한다.
|
||||
- 자동 배치한 경우 결과 보고에 선택한 삽입 단위, Phase/Milestone/태스크 위치, 판단 근거를 짧게 남긴다.
|
||||
|
||||
## 삽입 단위 정책
|
||||
|
||||
신규 추가 요청은 먼저 "어디에 둘지"와 "어떤 단위로 둘지"를 분리해서 판단한다. 여기서 태스크는 Milestone 문서 `필수 기능` 섹션의 체크리스트 항목 또는 기존 체크리스트 항목을 뜻한다.
|
||||
|
||||
| 삽입 단위 | 사용 기준 |
|
||||
|-----------|-----------|
|
||||
| 새 Milestone | 독립적인 목표와 완료 기준이 필요하거나, 여러 기능을 묶는 산출물이고, 별도 상태 추적이 필요하며, Phase 흐름이나 선후 의존성에 의미 있는 경계를 만든다 |
|
||||
| 기존 Milestone의 태스크 | 기존 Milestone의 목표와 범위 안에 들어가며, 하나의 완료 가능한 capability/산출물이지만 별도 Milestone 상태 추적까지는 필요하지 않다 |
|
||||
| 기존 태스크의 하위 작업 | 기존 태스크의 구현 세부, 보완, 테스트, 문서화, 예외 처리, 완료 기준 보완처럼 부모 태스크를 완성하기 위한 세부 항목이다. 잠긴 Milestone이어도 현재 작업에 직접 영향을 주는 사용자 결정이 없고 표준선으로 처리 가능하면 사용할 수 있다 |
|
||||
| 작업 컨텍스트/TODO | 사용자 결정이 아니라 조사/확인이 먼저 필요해 필수 기능으로 확정하기 어렵다 |
|
||||
|
||||
- 신규 Milestone은 사용자만 결정할 수 있는 항목이 있으면 `구현 잠금: 잠금`, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없으면 `구현 잠금: 해제`로 생성한다.
|
||||
- 잠긴 Milestone 안에 새 작업을 추가할 때 현재 요청에 직접 걸리는 사용자 결정은 `결정 필요` 체크리스트로 옮기고, 표준선으로 처리 가능한 세부 작업은 관련 `필수 기능` 항목의 하위 작업이나 `작업 컨텍스트`로 배치한다.
|
||||
- `구현 잠금`이 없거나 잠긴 Milestone에 대해 사용자가 작업, 구현, 계획 작성을 명시하면 현재 요청에 직접 영향을 주는 결정 필요 항목이 남아 있는지 먼저 판단한다. 남은 결정이 없으면 잠금을 유지하더라도 표준선으로 요청한 작업을 이어갈 수 있고, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 상태를 `해제`로 갱신한다.
|
||||
- 위치 지정이 있으면 anchor의 레벨을 먼저 확인한다. `<anchor-task> 아래`처럼 하위 위치가 명시되면 기존 태스크 하위 항목으로 넣고, `<anchor-task> 앞/뒤`면 같은 목록 레벨의 형제 항목으로 넣는다.
|
||||
- 사용자가 item-id를 언급하면 해당 Milestone의 `필수 기능` 체크리스트에서 정확히 일치하는 item-id를 우선 매칭한다. 중복되거나 없으면 임의로 고르지 말고 확인한다.
|
||||
- 여러 Milestone 후보에서 같은 item-id가 발견되면 item-id만으로 확정하지 말고 Milestone 이름이나 문서 경로를 확인한다.
|
||||
- 위치는 지정됐지만 단위가 명시되지 않은 경우, anchor 레벨과 작업 성격을 함께 보고 새 Milestone, 태스크, 하위 작업 중 하나를 선택한다.
|
||||
- 위치 지정이 `<phase-name> 안` 또는 `<milestone-name> 안`처럼 컨테이너만 지정된 경우, 해제된 Milestone에서 작업 내용이 기존 태스크의 세부 구현이면 해당 컨테이너 안에서 가장 관련 있는 태스크 아래에 넣을 수 있다. 이 경우 결과 보고에 "위치는 지정된 컨테이너를 따랐고, 단위는 하위 작업으로 판단"처럼 남긴다.
|
||||
- 위치 지정이 `<anchor-milestone> 앞/뒤` 또는 `<anchor-task> 앞/뒤`처럼 순서 anchor인 경우, 같은 레벨의 앞/뒤 배치를 유지한다. 작업 성격상 다른 레벨이 더 적절해 보여도 조용히 재배치하지 말고 사용자에게 확인한다.
|
||||
- `placement-unit`을 사용자가 명시한 경우 그 단위를 우선한다. 다만 지정 단위가 anchor 레벨, Milestone 목표, 범위 제외, 명백한 선후 의존성과 충돌하면 수정 전에 충돌 내용을 알리고 방향을 확인한다.
|
||||
- 작업이 둘 이상의 Milestone에 걸치면 바로 하나의 기존 태스크에 넣지 않는다. 공통 기반 작업이면 새 Milestone을 고려하고, 단순 연계 작업이면 각 Milestone에 나눌지 사용자에게 확인한다.
|
||||
- 기존 태스크와 중복되거나 기존 태스크의 완료 기준으로 자연스럽게 흡수되는 요청은 새 Milestone이나 새 형제 태스크로 만들지 말고 기존 태스크를 보완한다.
|
||||
|
||||
### current.md 형식
|
||||
|
||||
`agent-ops/roadmap/current.md`는 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식을 유지한다.
|
||||
|
||||
`current.md`는 개인별 작업 위치나 완료 상태의 진실이 아니다. 현재 열려 있는 Milestone 후보 목록이며, 실제 현 작업 지점과 남은 작업은 `analyze-roadmap-position` 스킬이 코드와 git 상태를 함께 읽고 분석한다.
|
||||
|
||||
## 먼저 확인할 것
|
||||
|
||||
- [ ] `agent-ops/roadmap/ROADMAP.md` 존재 여부 확인
|
||||
- [ ] `agent-ops/roadmap/current.md` 존재 여부 확인
|
||||
- [ ] `current.md`가 가리키는 활성 Milestone 문서 존재 여부 확인
|
||||
- [ ] `current.md`가 `agent-ops/roadmap/archive/**` 경로를 가리키지 않는지 확인
|
||||
- [ ] `current.md`가 정해진 한국어 형식을 유지하는지 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-template.md`를 읽어 최신 ROADMAP 형식 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-current-template.md`를 읽어 최신 current.md 형식 확인
|
||||
- [ ] `agent-ops/skills/common/_templates/roadmap-milestone-template.md`를 읽어 최신 Milestone 형식 확인
|
||||
- [ ] 로드맵 파일이 없으면 `create-roadmap` 스킬 사용을 안내하고 중단
|
||||
- [ ] 완료 상태로 바꾸는 경우 사용자의 명시 또는 확인 가능한 evidence가 있는지 확인
|
||||
- [ ] archive 모드이면 대상 Milestone이 `agent-ops/roadmap/milestones/` 하위에 있고, `ROADMAP.md`에 남길 요약 근거가 있는지 확인
|
||||
- [ ] 대상 Milestone의 `구현 잠금` 상태와 `결정 필요` 체크리스트를 확인. 섹션이 없거나 잠금 상태에서 작업/구현/계획 작성을 요청받은 경우 현재 요청에 직접 영향을 주는 사용자 결정이 남아 있는지 판단한다.
|
||||
- [ ] Milestone 전체에서 사용자만 결정할 항목이 더 이상 없으면 `구현 잠금`을 `해제`로 두고, 현재 요청과 직접 관련 없더라도 사용자 결정 항목이 남아 있으면 `잠금` 상태와 체크리스트를 유지한다.
|
||||
|
||||
## 실행 절차
|
||||
|
||||
1. **갱신 범위 결정**
|
||||
- 요청에서 mode, target Milestone, new feature, placement, placement-unit을 추론한다.
|
||||
- 요청이 Milestone 방향/범위 보완, 잠금 해제, 결정 필요 항목 정리, 또는 잠긴 Milestone의 작업/구현/계획 작성이면 `concretize`로 본다.
|
||||
- 요청이 완료 또는 폐기된 Milestone을 과거 기록으로 넘기는 것이라면 `archive`로 본다.
|
||||
- 로드맵 언어 전환, ROADMAP/current 형식 표준화, 또는 Milestone 형식 표준화 요청이면 `sync`로 보고 `ROADMAP.md`, `current.md`, `agent-ops/roadmap/milestones/` 하위 Milestone 문서를 갱신 범위에 포함할 수 있다.
|
||||
- `sync` 또는 템플릿 표준화 요청에서도 `agent-ops/roadmap/archive/**`는 갱신 범위에 포함하지 않는다.
|
||||
- `status` 갱신이면 `current.md`와 대상 Milestone 문서를 우선 읽는다.
|
||||
- `archive`이면 `ROADMAP.md`, `current.md`, 대상 Milestone 문서만 읽고 아카이브 디렉터리의 다른 문서는 읽지 않는다.
|
||||
- 요청이 활성 Milestone에 없으면 `ROADMAP.md`의 Milestone 목록을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
|
||||
- Phase 전환, Milestone 추가/삭제, 순서 변경, 전체 재계획이면 `ROADMAP.md`도 읽는다.
|
||||
- 신규 작업 추가이고 placement가 명시되어 있으면 anchor의 종류(Phase, Milestone, 태스크), 앞/뒤/안/아래 방향, 대상 Phase 또는 Milestone을 함께 기록한다.
|
||||
- 불필요하게 모든 Milestone 문서를 읽지 않는다.
|
||||
|
||||
2. **현재 로드맵 상태 파악**
|
||||
- `ROADMAP.md`의 전체 목표, Phase 흐름, Milestone 목록, 아카이브 Milestone 요약을 확인한다.
|
||||
- `current.md`의 활성 Milestone 창과 선택 규칙을 확인한다.
|
||||
- `current.md`에 아카이브 경로가 있으면 해당 항목을 읽지 말고 제거 대상으로 기록한다.
|
||||
- `ROADMAP.md`와 `current.md`가 표준 템플릿 섹션 순서와 형식을 따르는지 확인한다.
|
||||
- 대상 또는 후보 Milestone 문서의 목표, 범위, 필수 기능, 완료 기준, 범위 제외 항목을 확인한다.
|
||||
- 대상 또는 후보 Milestone 문서의 `구현 잠금` 상태와 `결정 필요` 항목을 확인한다.
|
||||
- `구현 잠금`이 없거나 잠긴 Milestone에 대한 작업, 구현, 구현 계획 요청이면 현재 요청에 직접 영향을 주는 사용자 결정이 남아 있는지 판단한다. 남은 결정이 없으면 잠금을 유지하더라도 표준선으로 요청한 작업을 이어갈 수 있고, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없는 경우에만 `구현 잠금` 상태를 `해제`로 갱신한다.
|
||||
- 대상 Milestone 문서가 표준 템플릿 섹션 순서와 체크리스트 형식을 따르는지 확인한다.
|
||||
- 대상 Milestone 문서의 `필수 기능` item-id 목록을 확인하고, 중복 또는 누락이 갱신 범위에 있으면 보정 대상으로 기록한다.
|
||||
- 신규 작업과 이름, 산출물, 코드 경계, 완료 기준이 겹치는 기존 태스크가 있는지 확인한다.
|
||||
|
||||
3. **신규 작업 삽입 단위와 위치 판단**
|
||||
- 추가 요청이면 placement, placement-unit, 작업 성격을 함께 보고 새 Milestone, 기존 Milestone의 태스크, 기존 태스크의 하위 작업, 작업 컨텍스트/TODO 중 어느 단위가 맞는지 결정한다.
|
||||
- 사용자가 위치를 지정한 경우 `ROADMAP.md`에서 anchor Phase/Milestone을 확인하고, 필요한 경우 대상 Milestone 문서의 태스크 anchor까지 확인해 충돌 여부를 확인한다.
|
||||
- 지정된 anchor가 없거나 여러 항목과 매칭되어 모호하면 임의 배치하지 말고 사용자에게 짧게 확인한다.
|
||||
- 사용자가 순서 anchor를 지정했으면 같은 레벨의 앞/뒤 배치를 유지하고, 컨테이너 anchor를 지정했으면 컨테이너 안에서 작업 성격에 맞는 하위 단위를 선택한다.
|
||||
- 위치 지정이 없으면 `ROADMAP.md`의 위아래 흐름, 현재 활성 Milestone, 선행되어야 할 작업, 후속 작업이 기대하는 산출물, 관련 코드/문서 경계, 기존 태스크와의 포함 관계를 기준으로 자동 배치한다.
|
||||
- 자동 배치는 "가장 빨리 할 수 있는 곳"이 아니라 "의존성과 완료 기준이 자연스럽게 이어지는 곳"을 우선한다.
|
||||
- 대상 Milestone이 잠겨 있으면 현재 요청에 직접 걸리는 사용자 판단은 `구현 잠금`의 `결정 필요` 체크리스트로 옮기고, 표준선으로 처리 가능한 새 항목은 capability/산출물/완료 기준 후보 또는 관련 기존 태스크의 하위 작업으로 배치한다.
|
||||
- 기존 태스크를 완성하는 세부 구현이면 하위 작업으로 넣고, 기존 태스크와 같은 수준의 독립 완료 항목이면 같은 Milestone의 태스크로 넣는다.
|
||||
- 기존 Milestone의 목표/범위를 넓히거나 완료 기준을 과도하게 키우는 작업이면 새 Milestone으로 분리한다.
|
||||
- 사용자 지정 위치가 Phase 목표, Milestone 범위 제외, 명백한 선후 의존성과 충돌하면 수정 전에 충돌 내용을 알리고 방향을 확인한다.
|
||||
|
||||
4. **변경 내용 검증**
|
||||
- 기능 완료 체크는 사용자 설명 또는 파일/테스트/커밋 등 확인 가능한 근거를 기준으로 한다.
|
||||
- evidence 없이 완료 여부가 불확실하면 체크하지 않고 TODO 또는 확인 필요로 남긴다.
|
||||
- 변경 요청이 전체 목표 또는 Phase 목표와 충돌하면 구현 전에 사용자에게 알리고 방향을 확인한다.
|
||||
|
||||
5. **로드맵 파일 갱신**
|
||||
- `ROADMAP.md`는 전체 목표, Phase 흐름, Milestone 목록, 아카이브 Milestone 요약, 로딩 정책이 바뀔 때만 수정한다.
|
||||
- `current.md`는 활성 Milestone 창이 바뀔 때 `roadmap-current-template.md` 형식으로 수정한다.
|
||||
- 갱신 대상 `ROADMAP.md`가 표준 템플릿과 다르면 기존 내용을 보존하면서 `전체 목표`, `Phase 흐름`, `Milestone 목록`, `아카이브 Milestone 요약`, `로딩 정책` 순서로 정리한다.
|
||||
- 갱신 대상 `current.md`가 표준 템플릿과 다르면 기존 활성 Milestone 목록을 보존하면서 `활성 Milestone`, `선택 규칙` 순서로 정리한다.
|
||||
- `current.md`에 `agent-ops/roadmap/archive/**` 경로가 있으면 활성 Milestone에서 제거하고, 필요하면 결과 보고의 확인 필요 항목에 남긴다.
|
||||
- `ROADMAP.md`에 상세 작업 체크리스트가 있으면 삭제하지 말고 관련 Milestone 문서의 `필수 기능` 체크리스트로 옮긴다.
|
||||
- `current.md`에 개인별 현재 작업 위치나 완료 상태가 있으면 `current.md`에서는 제거하고 공유 로드맵으로 이관하지 않는다. 프로젝트에 의미 있는 근거가 명확한 내용만 관련 Milestone 문서나 작업 컨텍스트로 옮기고, 이관하지 않은 내용은 결과 보고의 확인 필요 항목에 남긴다.
|
||||
- Milestone 문서는 해당 Milestone의 목표, 범위, 필수 기능, 완료 기준, 범위 제외, 작업 컨텍스트가 바뀔 때 수정한다.
|
||||
- 갱신 대상 Milestone 문서가 표준 템플릿과 다르면 기존 내용을 보존하면서 템플릿 섹션 순서로 정리하고, 누락 섹션은 TODO 또는 확인 필요 표시와 함께 추가한다.
|
||||
- 갱신 대상 Milestone 문서에 `구현 잠금` 섹션이 없으면 추가하고, 사용자만 결정할 수 있는 항목이 남아 있는지에 따라 상태를 정한다.
|
||||
- `concretize` 모드에서는 구현 세부를 무작정 채우지 말고, 사용자 요청에 필요한 방향/범위 보완, 표준선 기록, 또는 잠금 상태 갱신만 반영한다.
|
||||
- `구현 잠금`을 갱신할 때는 `결정 필요` 항목이 남아 있는지 결과 보고에 남긴다. 이 갱신만으로 `필수 기능`이나 `완료 기준`을 완료 처리하지 않는다.
|
||||
- 새 Milestone은 사용자 지정 또는 자동 판단 위치에 삽입하고, 기존 Milestone 이름이나 파일명을 순서 맞춤 목적으로 바꾸지 않는다.
|
||||
- 새 Milestone은 사용자만 결정할 수 있는 항목이 있으면 `잠금`, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없으면 `해제`로 작성한다.
|
||||
- 기존 Milestone에 새 태스크를 넣는 경우 `필수 기능` 체크리스트에 사용자 지정 또는 자동 판단 위치로 삽입하고, 근거 없이 목록 맨 앞이나 맨 뒤에 붙이지 않는다.
|
||||
- 해제된 Milestone에서 기존 태스크의 하위 작업으로 넣는 경우 부모 태스크 아래의 하위 체크리스트로 작성하고, 부모 태스크의 의미가 바뀌면 부모 문장도 필요한 만큼만 보완한다.
|
||||
- 새로 추가하거나 형식 보정 범위에 포함된 `필수 기능` 항목은 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식으로 작성한다.
|
||||
- 기존 `필수 기능`이 일반 불릿이면 상태 근거를 보존해 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 체크리스트로 변환한다.
|
||||
- 기존 `필수 기능` 체크리스트에 item-id가 있으면 사용자가 명시적으로 바꾸라고 하지 않는 한 유지한다. item-id가 없는 항목을 갱신 범위에서 보정할 때는 해당 Milestone 안에서 중복되지 않는 id를 붙인다.
|
||||
- 기존 `완료 기준`이 일반 불릿이면 검증 조건 단위의 체크리스트로 변환한다.
|
||||
- 상태 값은 `계획`, `진행 중`, `완료`, `보류`, `폐기` 중 하나만 사용한다.
|
||||
- 단순 상태 갱신이면 완료된 Milestone의 기록을 삭제하지 않고 상태만 변경한다.
|
||||
- `archive` 모드에서는 대상 Milestone의 최종 상태를 `완료` 또는 `폐기`로 확정할 근거가 있는지 확인한 뒤 진행한다.
|
||||
- `archive` 모드에서는 대상 Milestone 문서에서 `ROADMAP.md`의 `아카이브 Milestone 요약`에 남길 요약을 추출하거나, 사용자가 준 `archive-summary`를 반영한다.
|
||||
- `archive` 모드에서는 `ROADMAP.md`의 `Milestone 목록`에서 대상 링크를 제거하고, `아카이브 Milestone 요약`에 상태, 아카이브일, 요약, 핵심 산출물/근거, 후속 영향을 짧게 추가한다.
|
||||
- `archive` 모드에서는 `current.md`의 활성 Milestone 목록에서 대상 Milestone을 제거한다.
|
||||
- `archive` 모드에서는 대상 파일을 `agent-ops/roadmap/archive/YYYY/MM/<milestone-slug>.md`로 이동하고, 아카이브 대상 경로가 이미 있으면 확장자 앞에 다음 숫자를 붙인다.
|
||||
- 아카이브로 이동한 Milestone 문서는 이동 전 내용 그대로 보존하고, 최신 템플릿에 맞춘 재포맷이나 체크리스트 보정을 하지 않는다.
|
||||
|
||||
6. **로드맵 룰 라우팅 점검**
|
||||
- `agent-ops/rules/common/rules.md`가 `agent-ops/roadmap/` 디렉터리 존재 시 `agent-ops/rules/common/rules-roadmap.md`를 읽도록 라우팅하는지 확인한다.
|
||||
- `agent-ops/rules/common/rules.md`와 `rules-roadmap.md`에 `agent-ops/roadmap/archive/**`를 명시 요청 없이 읽지 않는 규칙이 있는지 확인한다.
|
||||
- `agent-ops/rules/common/rules-roadmap.md`에 `current.md` 의미, Milestone 선택, `ROADMAP.md` 로딩 조건, 구현 잠금, 현재 작업 지점 확인 방법, Milestone archive 정책이 포함되어 있는지 확인한다.
|
||||
- 로드맵 컨텍스트 로딩 규칙은 공통 로드맵 룰에 둔다. 프로젝트 전용 `rules/project/rules.md`에는 중복 마일스톤 컨텍스트 로딩 섹션을 추가하지 않는다.
|
||||
- 기존 프로젝트 규칙에 마일스톤 컨텍스트 로딩 섹션이 남아 있으면 프로젝트 고유 내용이 아닌지 확인하고, 공통 룰과 중복되는 내용은 제거 대상으로 보고한다.
|
||||
|
||||
7. **결과 보고**
|
||||
- 수정한 파일 목록
|
||||
- 변경된 Phase / Milestone / 상태
|
||||
- 신규 작업의 삽입 단위와 배치 위치, 자동 배치인 경우 판단 근거
|
||||
- ROADMAP/current/Milestone 문서 템플릿 보정 여부
|
||||
- 활성 Milestone 창 변경 사항
|
||||
- archive 모드이면 아카이브 경로와 `ROADMAP.md`에 남긴 요약
|
||||
- 체크하거나 추가/제거한 태스크 또는 하위 작업
|
||||
- 확인 필요로 남긴 항목
|
||||
|
||||
## 실행 결과 검증
|
||||
|
||||
- [ ] `current.md`의 활성 Milestone 경로가 실제 파일을 가리키는가
|
||||
- [ ] `current.md`의 활성 Milestone 경로가 `agent-ops/roadmap/archive/**`를 가리키지 않는가
|
||||
- [ ] `ROADMAP.md`가 `roadmap-template.md`의 섹션 순서와 형식을 따르는가
|
||||
- [ ] `ROADMAP.md`에 `아카이브 Milestone 요약` 섹션이 있는가
|
||||
- [ ] `current.md`가 `roadmap-current-template.md`의 섹션 순서와 형식을 따르는가
|
||||
- [ ] `ROADMAP.md`의 Milestone 목록과 대상 Milestone 문서의 상태가 서로 충돌하지 않는가
|
||||
- [ ] 갱신 대상 Milestone 문서가 `roadmap-milestone-template.md`의 섹션 순서와 형식을 따르는가
|
||||
- [ ] 갱신 대상 Milestone 문서에 `구현 잠금` 섹션이 있는가
|
||||
- [ ] 잠금 상태인 Milestone의 `구현 잠금` 섹션에 사용자만 결정할 수 있는 항목이 체크리스트로 남아 있는가
|
||||
- [ ] `구현 잠금`이 없거나 잠긴 Milestone에 현재 요청과 직접 관련된 사용자 결정 필요 항목을 확인하지 않은 채 구현 태스크, `agent-task` 계획, 세부 API/파일 구조 확정을 추가하지 않았는가
|
||||
- [ ] 잠금 상태를 갱신한 경우 결정 필요 항목이 남아 있는지 결과 보고에 남겼는가
|
||||
- [ ] 갱신 대상 Milestone 문서의 `필수 기능`과 `완료 기준`이 체크리스트 형식인가
|
||||
- [ ] 갱신 대상 Milestone 문서의 `필수 기능` 체크리스트 항목이 `- [ ] [item-id] 설명` 형식이고 item-id가 해당 Milestone 안에서 유일한가
|
||||
- [ ] 신규 작업이 사용자 지정 위치를 따랐거나, 위치 미지정 시 자동 배치 근거가 남아 있는가
|
||||
- [ ] 신규 작업의 삽입 단위가 작업 성격과 기존 태스크 포함 관계에 맞는가
|
||||
- [ ] 자동 배치 위치가 Phase/Milestone 목표, 범위 제외 항목, 선후 의존성과 충돌하지 않는가
|
||||
- [ ] 대상 Milestone 문서의 상태가 `계획`, `진행 중`, `완료`, `보류`, `폐기` 중 하나인가
|
||||
- [ ] 완료 처리한 기능에 사용자 설명 또는 확인 가능한 evidence가 있는가
|
||||
- [ ] archive 모드이면 대상 Milestone이 `Milestone 목록`과 `current.md`에서 제거되고 `아카이브 Milestone 요약`에 당시 요약이 남았는가
|
||||
- [ ] archive 모드이면 이동한 문서를 최신 템플릿으로 재포맷하지 않았는가
|
||||
- [ ] `rules/common/rules.md`가 로드맵 디렉터리 존재 시 `rules-roadmap.md`를 읽도록 라우팅하는가
|
||||
- [ ] `rules/common/rules-roadmap.md`에 로드맵 컨텍스트 로딩, 구현 잠금, 아카이브 제외 규칙이 유지되는가
|
||||
- 검증 실패 시: 불일치한 파일만 다시 읽고 해당 항목만 수정한다.
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```markdown
|
||||
## 업데이트 완료
|
||||
|
||||
- 모드: <status | milestone | phase | replan | sync | concretize | archive>
|
||||
- 수정 파일: <해당 항목만 나열>
|
||||
- agent-ops/roadmap/ROADMAP.md
|
||||
- agent-ops/roadmap/current.md
|
||||
- agent-ops/roadmap/milestones/<milestone-slug>.md
|
||||
- agent-ops/roadmap/archive/YYYY/MM/<milestone-slug>.md (archive 모드)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
- Phase: <변경 없음 | 요약>
|
||||
- 삽입 단위: <Milestone | 태스크 | 하위 작업 | 작업 컨텍스트/TODO | 변경 없음>
|
||||
- 배치: <사용자 지정 위치 반영 | 자동 배치 위치와 근거 | 변경 없음>
|
||||
- 템플릿 보정: <ROADMAP 적용 | current.md 적용 | Milestone 적용 | 이미 일치 | 변경 없음>
|
||||
- 구현 잠금: <잠금 유지 | 잠금 추가 | 해제 | 변경 없음>; 결정 필요: <없음 | 항목 요약>
|
||||
- 활성 Milestone: <변경 없음 | 추가/제거 요약>
|
||||
- 아카이브: <변경 없음 | 이동 경로와 ROADMAP 요약>
|
||||
- 상태: <변경 없음 | 이전 -> 이후>
|
||||
- 태스크: <추가/수정/완료/제거 요약>
|
||||
|
||||
## TODO 항목
|
||||
|
||||
- <확인이 필요한 항목> (해당 시)
|
||||
```
|
||||
|
||||
## 금지 사항
|
||||
|
||||
- 로드맵 파일이 없는데 새 구조를 임의로 만들지 않는다. 이 경우 `create-roadmap`을 사용한다.
|
||||
- evidence 없이 기능이나 Milestone을 완료 처리하지 않는다.
|
||||
- 전체 `ROADMAP.md`를 모든 작업의 필수 로딩 파일로 만들지 않는다.
|
||||
- `ROADMAP.md`에 상세 작업 체크리스트를 남기지 않는다.
|
||||
- `current.md`에 개인별 현재 작업 위치나 완료 상태를 남기지 않는다.
|
||||
- `current.md`에 `agent-ops/roadmap/archive/**` 경로를 남기지 않는다.
|
||||
- 완료된 Milestone 기록을 삭제하지 않는다.
|
||||
- 아카이브된 Milestone 문서를 명시 요청 없이 읽거나 최신 템플릿으로 재포맷하지 않는다.
|
||||
- 아카이브된 Milestone을 `ROADMAP.md`의 활성 `Milestone 목록`에 링크로 계속 남기지 않는다.
|
||||
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
|
||||
- 기존 순번 파일명을 대규모 rename하지 않는다.
|
||||
- 신규 작업을 근거 없이 항상 새 Milestone으로 만들거나 맨 앞/맨 뒤에 추가하지 않는다.
|
||||
- 작업 성격과 기존 태스크 포함 관계를 확인하지 않고 모든 신규 작업을 같은 단위로 처리하지 않는다.
|
||||
- `구현 잠금`이 없거나 잠긴 Milestone에 대해 현재 요청과 직접 관련된 `결정 필요` 항목을 확인하기 전에 코드 구현, `agent-task` 구현 계획, 세부 API/파일 구조 확정을 시작하지 않는다.
|
||||
- 현재 요청과 직접 관련 없는 미정 항목만 남아 있거나 표준선으로 처리 가능한 작업까지 잠금 상태라는 이유만으로 막지 않는다.
|
||||
- 사용자만 결정할 수 있는 항목이 남아 있는데 Milestone의 `구현 잠금`을 `해제`로 바꾸지 않는다.
|
||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없는 Milestone을 관성적으로 `잠금` 상태로 두지 않는다.
|
||||
- 초기 Milestone을 구현 계획처럼 자세한 package/file/function 체크리스트로 채우지 않는다.
|
||||
- 사용자가 지정한 앞/뒤/아래 anchor 또는 대상 Phase/Milestone 컨테이너를 무시하지 않는다.
|
||||
- Milestone 목표와 범위 제외 항목을 무시하고 태스크 체크리스트만 갱신하지 않는다.
|
||||
- 해야 할 작업을 `필수 기능` 체크리스트 밖의 설명 문장에 숨기지 않는다.
|
||||
- 사용자가 명시하지 않은 기존 `필수 기능` item-id를 바꾸지 않는다.
|
||||
- 갱신 대상 Milestone의 형식이 다르다는 이유로 기존 내용이나 완료 체크 근거를 삭제하지 않는다.
|
||||
- 타겟 프로젝트에서 `agent-ops/rules/common/` 또는 `agent-ops/skills/common/`을 직접 수정하지 않는다.
|
||||
14
apps/cli/cmd/alt/main.go
Normal file
14
apps/cli/cmd/alt/main.go
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) > 1 && os.Args[1] == "version" {
|
||||
fmt.Println("alt dev")
|
||||
return
|
||||
}
|
||||
fmt.Println("ALT operator CLI")
|
||||
}
|
||||
3
apps/cli/go.mod
Normal file
3
apps/cli/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module git.toki-labs.com/toki/alt/apps/cli
|
||||
|
||||
go 1.22
|
||||
45
apps/client/.gitignore
vendored
Normal file
45
apps/client/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.build/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
/coverage/
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
45
apps/client/.metadata
Normal file
45
apps/client/.metadata
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
- platform: android
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
- platform: ios
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
- platform: linux
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
- platform: macos
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
- platform: web
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
- platform: windows
|
||||
create_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
base_revision: 2c9eb20739dfec95e2c74bd3dfa4601b0a8a36aa
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
12
apps/client/README.md
Normal file
12
apps/client/README.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# ALT Client
|
||||
|
||||
Flutter client for ALT web, mobile, and desktop targets.
|
||||
|
||||
This app uses Riverpod for state and dependency boundaries, and `go_router` for navigation. ALT protobuf bindings and the proto-socket client layer should be added under `lib/src` after `packages/contracts` generation is introduced.
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
flutter run -d chrome
|
||||
flutter test
|
||||
flutter analyze --no-fatal-infos
|
||||
```
|
||||
28
apps/client/analysis_options.yaml
Normal file
28
apps/client/analysis_options.yaml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at https://dart.dev/lints.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
14
apps/client/android/.gitignore
vendored
Normal file
14
apps/client/android/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
.cxx/
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/to/reference-keystore
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
44
apps/client/android/app/build.gradle.kts
Normal file
44
apps/client/android/app/build.gradle.kts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tokilabs.alt_client"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.tokilabs.alt_client"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
7
apps/client/android/app/src/debug/AndroidManifest.xml
Normal file
7
apps/client/android/app/src/debug/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
45
apps/client/android/app/src/main/AndroidManifest.xml
Normal file
45
apps/client/android/app/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="ALT"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tokilabs.alt_client
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity()
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
BIN
apps/client/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
BIN
apps/client/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
BIN
apps/client/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
BIN
apps/client/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 442 B |
Binary file not shown.
|
After Width: | Height: | Size: 721 B |
Binary file not shown.
|
After Width: | Height: | Size: 1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
18
apps/client/android/app/src/main/res/values-night/styles.xml
Normal file
18
apps/client/android/app/src/main/res/values-night/styles.xml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
18
apps/client/android/app/src/main/res/values/styles.xml
Normal file
18
apps/client/android/app/src/main/res/values/styles.xml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
7
apps/client/android/app/src/profile/AndroidManifest.xml
Normal file
7
apps/client/android/app/src/profile/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
24
apps/client/android/build.gradle.kts
Normal file
24
apps/client/android/build.gradle.kts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
val newBuildDir: Directory =
|
||||
rootProject.layout.buildDirectory
|
||||
.dir("../../build")
|
||||
.get()
|
||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||
|
||||
subprojects {
|
||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
}
|
||||
|
||||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.layout.buildDirectory)
|
||||
}
|
||||
2
apps/client/android/gradle.properties
Normal file
2
apps/client/android/gradle.properties
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
5
apps/client/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
apps/client/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
||||
26
apps/client/android/settings.gradle.kts
Normal file
26
apps/client/android/settings.gradle.kts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
pluginManagement {
|
||||
val flutterSdkPath =
|
||||
run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.11.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
34
apps/client/ios/.gitignore
vendored
Normal file
34
apps/client/ios/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
**/dgph
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
**/*sync/
|
||||
.sconsign.dblite
|
||||
.tags*
|
||||
**/.vagrant/
|
||||
**/DerivedData/
|
||||
Icon?
|
||||
**/Pods/
|
||||
**/.symlinks/
|
||||
profile
|
||||
xcuserdata
|
||||
**/.generated/
|
||||
Flutter/App.framework
|
||||
Flutter/Flutter.framework
|
||||
Flutter/Flutter.podspec
|
||||
Flutter/Generated.xcconfig
|
||||
Flutter/ephemeral/
|
||||
Flutter/app.flx
|
||||
Flutter/app.zip
|
||||
Flutter/flutter_assets/
|
||||
Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
||||
24
apps/client/ios/Flutter/AppFrameworkInfo.plist
Normal file
24
apps/client/ios/Flutter/AppFrameworkInfo.plist
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
1
apps/client/ios/Flutter/Debug.xcconfig
Normal file
1
apps/client/ios/Flutter/Debug.xcconfig
Normal file
|
|
@ -0,0 +1 @@
|
|||
#include "Generated.xcconfig"
|
||||
1
apps/client/ios/Flutter/Release.xcconfig
Normal file
1
apps/client/ios/Flutter/Release.xcconfig
Normal file
|
|
@ -0,0 +1 @@
|
|||
#include "Generated.xcconfig"
|
||||
620
apps/client/ios/Runner.xcodeproj/project.pbxproj
Normal file
620
apps/client/ios/Runner.xcodeproj/project.pbxproj
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C807F294A63A400263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C807D294A63A400263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tokilabs.altClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tokilabs.altClient.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tokilabs.altClient.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tokilabs.altClient.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tokilabs.altClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tokilabs.altClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
7
apps/client/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
apps/client/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||
BuildableName = "RunnerTests.xctest"
|
||||
BlueprintName = "RunnerTests"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
7
apps/client/ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
apps/client/ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue