init: agent-ops, AI assistant rules, and configuration files add

This commit is contained in:
toki 2026-05-26 13:29:38 +09:00
parent 60eb73c281
commit d7a96eb460
64 changed files with 5081 additions and 27 deletions

4
.aiexclude Normal file
View file

@ -0,0 +1,4 @@
# BEGIN Agent-Ops managed ignore
agent-task/archive/**
agent-ops/roadmap/archive/**
# END Agent-Ops managed ignore

8
.claude/settings.json Normal file
View file

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"deny": [
"Read(./agent-task/archive/**)"
]
}
}

4
.clineignore Normal file
View file

@ -0,0 +1,4 @@
# BEGIN Agent-Ops managed ignore
agent-task/archive/**
agent-ops/roadmap/archive/**
# END Agent-Ops managed ignore

30
.clinerules Normal file
View file

@ -0,0 +1,30 @@
# 공통 규칙
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
- 요청 범위를 넘는 변경을 하지 않는다.
- 불확실하면 단정하지 말고 후보를 제시한다.
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
- `agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
**세션 최초 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 업데이트 / 진입 파일 재적용

4
.cursorignore Normal file
View file

@ -0,0 +1,4 @@
# BEGIN Agent-Ops managed ignore
agent-task/archive/**
agent-ops/roadmap/archive/**
# END Agent-Ops managed ignore

30
.cursorrules Normal file
View file

@ -0,0 +1,30 @@
# 공통 규칙
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
- 요청 범위를 넘는 변경을 하지 않는다.
- 불확실하면 단정하지 말고 후보를 제시한다.
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
- `agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
**세션 최초 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 업데이트 / 진입 파일 재적용

4
.geminiignore Normal file
View file

@ -0,0 +1,4 @@
# BEGIN Agent-Ops managed ignore
agent-task/archive/**
agent-ops/roadmap/archive/**
# END Agent-Ops managed ignore

30
AGENTS.md Normal file
View file

@ -0,0 +1,30 @@
# 공통 규칙
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
- 요청 범위를 넘는 변경을 하지 않는다.
- 불확실하면 단정하지 말고 후보를 제시한다.
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
- `agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
**세션 최초 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 업데이트 / 진입 파일 재적용

30
CLAUDE.md Normal file
View file

@ -0,0 +1,30 @@
# 공통 규칙
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
- 요청 범위를 넘는 변경을 하지 않는다.
- 불확실하면 단정하지 말고 후보를 제시한다.
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
- `agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
**세션 최초 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 업데이트 / 진입 파일 재적용

30
GEMINI.md Normal file
View file

@ -0,0 +1,30 @@
# 공통 규칙
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
- 요청 범위를 넘는 변경을 하지 않는다.
- 불확실하면 단정하지 말고 후보를 제시한다.
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
- `agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
**세션 최초 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 업데이트 / 진입 파일 재적용

134
README.md
View file

@ -1,40 +1,120 @@
# nexo
nexo is a messaging and notification service workspace.
`nexo` is a messaging and notification service workspace that keeps the server
core, Flutter client, and Flutter push-notification package together.
The repository keeps the runtime pieces together so server, Flutter client, and
notification package changes can move in one branch while each module keeps a
clear boundary.
The current goal is to preserve the proven Mattermost-based messaging and push
runtime while moving toward an independent product shape with Nexo-owned service
boundaries.
## Layout
## Current Status
```text
nexo/
apps/client/ # Flutter client and integration test host
services/core/ # Mattermost-derived messaging server core
packages/messaging_flutter/ # Flutter notification/messaging plugin package
docs/ # Product and migration notes
bin/ # Workspace helper entrypoints
```
- `services/core/` is a Mattermost `v11.4.2` based server core and compose runtime.
- `packages/messaging_flutter/` is an Android-first Flutter push-notification plugin.
- `apps/client/` is the Flutter client and integration test host for the plugin.
- The plugin public package name remains `mattermost_push_plugin` for compatibility.
- iOS and macOS plugin scaffolds exist, but Android is the current implementation target.
## Current Baseline
## Quick Start
- `services/core/` is based on Mattermost `v11.4.2`, matching the observed
server runtime used during migration.
- `packages/messaging_flutter/` is migrated from `mattermost-push-plugin`.
Existing public identifiers are intentionally kept for compatibility during
the first move.
- `apps/client/` is the former plugin example app promoted to the workspace
client/test host.
## Commands
Show development entrypoints:
```sh
bin/dev
bin/test
bin/lint
bin/build
```
Core server Docker files live under `services/core/compose/`.
Run Flutter package and client checks:
```sh
bin/test
bin/lint
```
Start the core compose runtime:
```sh
cd services/core/compose
cp .env.example .env
docker compose up
```
## Commands
| Purpose | Command | Notes |
| --- | --- | --- |
| Show development entrypoints | `bin/dev` | Prints client, plugin, and core compose commands |
| Run default tests | `bin/test` | Runs Flutter tests; skips Go tests by default |
| Run default lint | `bin/lint` | Runs Flutter analyze; skips Go vet by default |
| Run default build | `bin/build` | Runs client web build; skips Go build by default |
| Include server Go tests | `NEXO_CORE_GO_TEST=1 bin/test` | Requires local `go` |
| Include server Go vet | `NEXO_CORE_GO_LINT=1 bin/lint` | Requires local `go` |
| Include server Go build | `NEXO_CORE_GO_BUILD=1 bin/build` | Requires local `go` |
| Run the client directly | `cd apps/client && flutter run` | Requires a device or emulator |
| Test the plugin directly | `cd packages/messaging_flutter && flutter test` | Requires Flutter SDK |
| Run Android native unit tests | `cd apps/client/android && ./gradlew testDebugUnitTest` | Requires Android SDK |
The `bin/*` helpers skip checks when a required local tool is unavailable. Note
any skipped checks in work reports.
## Structure
| Path | Role |
| --- | --- |
| `services/core/` | Mattermost `v11.4.2` based messaging server core, webapp, and API docs |
| `services/core/compose/` | Compose setup for core, Postgres, and push-proxy |
| `packages/messaging_flutter/` | Flutter push notification and messaging plugin |
| `apps/client/` | Flutter client and integration test host |
| `docs/` | Cross-module product, migration, and operations notes |
| `bin/` | Workspace helper entrypoints |
| `agent-ops/` | Agent rules, domain rules, and common skill entrypoints |
## Work Context
- Start by reading `AGENTS.md`, then `agent-ops/rules/project/rules.md`.
- Follow path-specific domain rules under `agent-ops/rules/project/domain/*/rules.md`.
- For standard tasks such as README, plan, review, or commit/push, route through `agent-ops/skills/common/router.md`.
- Do not change `services/core/UPSTREAM.md` baseline information without an explicit upstream decision.
- Keep product-specific `services/core/` changes small and easy to compare against upstream.
- Keep `apps/client/` as a thin consumer test host; do not duplicate plugin internals there.
## Development Flow
1. Read the domain rule for the path you will change.
2. Make focused changes inside the owning module.
3. Run the smallest useful verification for the change.
4. Use `bin/test`, `bin/lint`, or `bin/build` when workspace-level checks are needed.
5. Use `services/core/compose/` when runtime server verification is needed.
## Environment Variables
### Core Compose
| Name | Description | Required |
| --- | --- | --- |
| `NEXO_DB_PASSWORD` | Password for the Postgres `mmuser` account | Yes |
| `NEXO_SITE_URL` | Site URL used by the core service | Yes |
| `NEXO_CORE_PORT` | Host port mapped to core `8065` | No |
| `NEXO_PUSH_PROXY_PORT` | Host port mapped to push-proxy `8066` | No |
See `services/core/compose/.env.example` for example values. Do not commit real
`.env` files or runtime data.
### Optional Verification
| Name | Description | Default |
| --- | --- | --- |
| `NEXO_CORE_GO_TEST` | Run server Go tests from `bin/test` | `0` |
| `NEXO_CORE_GO_LINT` | Run server Go vet from `bin/lint` | `0` |
| `NEXO_CORE_GO_BUILD` | Run server Go build from `bin/build` | `0` |
## Reference Documents
- `AGENTS.md`
- `agent-ops/rules/project/rules.md`
- `agent-ops/skills/common/router.md`
- `services/core/UPSTREAM.md`
- `services/core/compose/README.md`
- `packages/messaging_flutter/README.md`
- `packages/messaging_flutter/docs/android-test-environment.md`
- `apps/client/README.md`
- `docs/README.md`

1
agent-ops/.version Normal file
View file

@ -0,0 +1 @@
1.1.67

219
agent-ops/bin/ai-ignore.sh Executable file
View file

@ -0,0 +1,219 @@
#!/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_BLOCK_BEGIN="# BEGIN Agent-Ops managed ignore"
AGENT_OPS_AI_IGNORE_BLOCK_END="# END Agent-Ops managed ignore"
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_ensure_ai_ignore_block() {
local file="$1"
local tmp
touch "$file"
if grep -qxF "$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" "$file" \
&& grep -qxF "$AGENT_OPS_AI_IGNORE_BLOCK_END" "$file"; then
tmp="$(mktemp "$file.tmp.XXXXXX")"
awk \
-v begin="$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" \
-v end="$AGENT_OPS_AI_IGNORE_BLOCK_END" \
-v task="$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" \
-v roadmap="$AGENT_OPS_ROADMAP_ARCHIVE_IGNORE_PATTERN" '
$0 == begin {
print begin
print task
print roadmap
print end
in_block = 1
next
}
$0 == end && in_block {
in_block = 0
next
}
!in_block { print }
' "$file" > "$tmp"
mv "$tmp" "$file"
else
if [[ -s "$file" ]]; then
printf "\n" >> "$file"
fi
printf "%s\n" "$AGENT_OPS_AI_IGNORE_BLOCK_BEGIN" >> "$file"
printf "%s\n" "$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" >> "$file"
printf "%s\n" "$AGENT_OPS_ROADMAP_ARCHIVE_IGNORE_PATTERN" >> "$file"
printf "%s\n" "$AGENT_OPS_AI_IGNORE_BLOCK_END" >> "$file"
fi
}
agent_ops_merge_json_with_jq() {
local file="$1"
local filter="$2"
local fallback_note="$3"
local tmp
if ! command -v jq >/dev/null 2>&1; then
echo "$fallback_note"
return
fi
tmp="$(mktemp "$file.tmp.XXXXXX")"
if jq "$filter" "$file" > "$tmp"; then
mv "$tmp" "$file"
else
rm -f "$tmp"
echo "$fallback_note"
fi
}
agent_ops_merge_claude_settings() {
local file="$1"
local filter='
def append_unique($item):
if index($item) then . else . + [$item] end;
def as_array:
if type == "array" then . elif . == null then [] else [.] end;
def as_object:
if type == "object" then . else {} end;
.permissions = ((.permissions // {}) | as_object)
| .permissions.deny = (
(.permissions.deny | as_array)
| map(select(. != "Read(./agent-ops/roadmap/archive/**)"))
| append_unique("Read(./agent-task/archive/**)")
)
'
agent_ops_merge_json_with_jq \
"$file" \
"$filter" \
"Note: .claude/settings.json exists; add Read(./agent-task/archive/**) and remove Read(./agent-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)
as $deny
| (($deny | index("Read(./agent-task/archive/**)")) != null)
and (($deny | index("Read(./agent-ops/roadmap/archive/**)")) == null)
'
if command -v jq >/dev/null 2>&1; then
jq -e "$filter" "$file" >/dev/null 2>&1
else
grep -q "agent-task/archive" "$file"
fi
}
agent_ops_merge_opencode_config() {
local file="$1"
local filter='
def append_unique($item):
if index($item) then . else . + [$item] end;
def as_array:
if type == "array" then . elif . == null then [] else [.] end;
def as_object:
if type == "object" then . else {} end;
.permission = ((.permission // {}) | as_object)
| .permission.read = ((.permission.read // {}) | as_object)
| .permission.read["agent-task/archive/**"] = "deny"
| del(.permission.read["agent-ops/roadmap/archive/**"])
| .permission.glob = ((.permission.glob // {}) | as_object)
| .permission.glob["agent-task/archive/**"] = "deny"
| del(.permission.glob["agent-ops/roadmap/archive/**"])
| .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/** read/glob deny, remove agent-ops/roadmap/archive/** read/glob hard deny, and add agent-task/archive/** plus agent-ops/roadmap/archive/** watcher ignore manually."
}
agent_ops_opencode_config_complete() {
local file="$1"
local filter='
def as_array:
if type == "array" then . elif . == null then [] else [.] end;
(.permission.read["agent-task/archive/**"] == "deny")
and (.permission.glob["agent-task/archive/**"] == "deny")
and (.permission.read["agent-ops/roadmap/archive/**"] != "deny")
and (.permission.glob["agent-ops/roadmap/archive/**"] != "deny")
and ((.watcher.ignore | as_array) as $ignore | (($ignore | index("agent-task/archive/**")) != null) and (($ignore | index("agent-ops/roadmap/archive/**")) != null))
'
if command -v jq >/dev/null 2>&1; then
jq -e "$filter" "$file" >/dev/null 2>&1
else
grep -q "agent-task/archive" "$file" && grep -q "agent-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_ensure_ai_ignore_block "$target_dir/$ignore_file"
done
mkdir -p "$target_dir/.claude"
if [[ ! -f "$target_dir/.claude/settings.json" ]]; then
cat > "$target_dir/.claude/settings.json" <<'EOF'
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"deny": [
"Read(./agent-task/archive/**)"
]
}
}
EOF
elif ! agent_ops_claude_settings_complete "$target_dir/.claude/settings.json"; then
agent_ops_merge_claude_settings "$target_dir/.claude/settings.json"
fi
if [[ ! -f "$target_dir/opencode.json" ]]; then
cat > "$target_dir/opencode.json" <<'EOF'
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": {
"agent-task/archive/**": "deny"
},
"glob": {
"agent-task/archive/**": "deny"
}
},
"watcher": {
"ignore": [
"agent-task/archive/**",
"agent-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
echo " AI permission 표준 적용: roadmap archive hard deny 제거"
}

28
agent-ops/bin/bump-version.sh Executable file
View 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"

View 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
View 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
View 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}"

View file

@ -0,0 +1,50 @@
# 로드맵
## 전체 목표
`nexo`는 Mattermost 기반 메시징 코어에서 검증된 서버/푸시 런타임을 계승하되,
제품 표면과 개발 경계는 독립적인 메시징/알림 서비스로 정리한다.
최종 형태는 서버 코어, Flutter 클라이언트, Flutter 플러그인이 한 세트로 움직이며,
여러 앱이 표준화된 메시징 채널과 알림 파이프라인을 사용할 수 있는 서비스다.
## Phase 흐름
위에서 아래로 진행된 순서와 예정 흐름을 나타낸다.
완료된 Phase도 로드맵에서 제거하지 않고, archive의 Phase 문서로 연결한다.
검토중 또는 진행중 Phase는 계획 Phase보다 위에 두어, 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Phase는 아직 구현 가능한 계획이 아니므로 계획 Phase보다 아래에 둔다.
- [진행중] 제품 기반 정리
- 경로: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
- 요약: nexo의 독립 제품 정체성, 모노레포 구조, 검증 가능한 런타임 기준선을 고정한다.
- [계획] 메시징 런타임 표준화
- 경로: `agent-ops/roadmap/phase/messaging-runtime/PHASE.md`
- 요약: 플러그인과 서버가 공유할 메시징/알림 계약, 테스트, 앱별 사용 채널 모델을 정리한다.
- [스케치] 독립 서비스화
- 경로: `agent-ops/roadmap/phase/independent-service/PHASE.md`
- 요약: Mattermost 호환 코어를 유지하되 제품 표면, 운영 방식, 불필요 기능을 nexo 목적에 맞게 분리한다.
## 로딩 정책
- 일반 작업에서는 `agent-ops/roadmap/ROADMAP.md`를 매번 읽지 않는다.
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-ops/roadmap/current.md`를 먼저 읽는다.
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 Milestone 후보 목록이다.
- `current.md`에는 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
- `current.md`의 활성 Phase는 `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
- `current.md`의 활성 Milestone은 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
- `current.md``agent-ops/roadmap/archive/**` 경로를 활성 항목으로 포함하지 않는다.
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 활성 Phase와 Milestone 문서를 같은 세션에서 1회 읽는다.
- 활성 Phase 또는 Milestone 밖의 작업이면 이 문서의 Phase 흐름을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
- 이 문서는 로드맵 생성/갱신, Phase 전환, Phase 추가/수정, 전체 구조 변경 요청이 있을 때만 읽는다.
- 상세 작업은 각 Milestone 문서의 `기능`으로 관리한다. 검증이 필요한 기능만 같은 Task 안에 `검증:`으로 통합한다.
- `[스케치]` Phase/Milestone은 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태이며 구현 계획 생성 대상이 아니다.
- `[스케치]` 항목은 `승격 조건`을 정리해 `[계획]`으로 전환한 뒤 구현 계획을 만든다.
- 모든 기능 Task와 Task 안에 명시된 검증이 충족된 Milestone은 먼저 `[검토중]`으로 두고, 사용자 완료 확인과 archive 승인을 받은 뒤 `[완료]`로 전환한다.
- 완료된 Phase는 `agent-ops/roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
- 진행중 Phase 안에서 완료된 Milestone은 활성 Phase 문서에 짧은 링크를 남기고, 상세 문서는 `agent-ops/roadmap/archive/phase/<phase-slug>/milestones/`로 이동한다.
- archive `PHASE.md`는 Phase 자체가 완료 또는 폐기될 때만 만들며, 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
- `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라가서 읽는다.
- 아카이브된 Phase/Milestone 문서는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획 생성, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조/도메인 rule/플랫폼 관례로 정할 수 있는 작업은 표준선으로 기록하고 진행할 수 있다.
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 `구현 잠금` 상태를 `해제`로 둔다.

View file

@ -0,0 +1,39 @@
# 현재 로드맵 컨텍스트
## 활성 Phase
- [진행중] 제품 기반 정리
- 경로: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
- [계획] 메시징 런타임 표준화
- 경로: `agent-ops/roadmap/phase/messaging-runtime/PHASE.md`
## 활성 Milestone
- [진행중] 정체성 기준선
- Phase: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
- 경로: `agent-ops/roadmap/phase/product-foundation/milestones/identity-baseline.md`
- [계획] 운영 기준선
- Phase: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
- 경로: `agent-ops/roadmap/phase/product-foundation/milestones/runtime-baseline.md`
- [계획] 클라이언트 검증 기준선
- Phase: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
- 경로: `agent-ops/roadmap/phase/product-foundation/milestones/client-validation.md`
- [계획] 메시징 계약 표준화
- Phase: `agent-ops/roadmap/phase/messaging-runtime/PHASE.md`
- 경로: `agent-ops/roadmap/phase/messaging-runtime/milestones/messaging-contract.md`
## 선택 규칙
- 이 문서는 활성 Phase와 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
- 활성 Phase는 `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
- 활성 Milestone은 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
- 활성 항목은 아카이브 경로를 포함하지 않는다.
- `[검토중]` 항목은 사용자 완료 확인 전까지 활성 항목으로 남길 수 있다.
- `[스케치]` 항목은 활성 후보로 남길 수 있지만 구현 계획 생성 대상은 아니며, `[계획]` 승격 조건을 정리하는 대상으로만 다룬다.
- `[완료]` 또는 `[폐기]` 항목은 archive 링크를 남긴 뒤 활성 항목에서 제거한다.
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 Phase와 Milestone을 선택하고 같은 세션에서 1회 읽는다.
- 활성 Phase 또는 Milestone 둘 이상에 걸치면 필요한 문서를 모두 읽고 작업 범위를 좁힌다.
- 활성 범위 밖의 작업이면 `agent-ops/roadmap/ROADMAP.md`의 Phase 흐름을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
- 완료된 과거 내용이 필요할 때만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 읽는다.
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 구현이나 구현 계획을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다. 관련 결정이 없고 표준선으로 처리 가능하면 잠금을 유지한 채 진행할 수 있으며, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 `구현 잠금` 상태를 `해제`로 둔다.
- 선택된 Milestone 상태가 `[스케치]`이면 `구현 잠금` 상태와 관계없이 구현이나 구현 계획을 시작하지 않고 `[계획]` 승격 필요를 보고한다.

View file

@ -0,0 +1,29 @@
# Phase: 독립 서비스화
## 상태
[스케치]
## 목표
nexo가 Mattermost 기반 코어를 사용한다는 구현 사실과, 사용자에게 제공하는 독립 메시징/알림 서비스라는 제품 표면을 분리한다.
장기적으로는 필요한 메시징 코어만 유지하고 불필요한 UI, 운영 기능, 이름, 문서 표면을 nexo 목적에 맞게 줄인다.
## Milestone 흐름
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
- [스케치] 서버 코어 독립화 경계
- 경로: `agent-ops/roadmap/phase/independent-service/milestones/core-independence.md`
- 요약: Mattermost core에서 계승할 기능과 제거/숨김/대체할 기능의 경계를 정한다.
- [스케치] 제품화와 운영 모델
- 경로: `agent-ops/roadmap/phase/independent-service/milestones/product-operations.md`
- 요약: nexo를 별도 서비스로 배포, 운영, 확장하기 위한 제품/운영 단위를 검토한다.
## Phase 경계
- 이 Phase는 아직 구현 계획이 아니라 장기 방향성 정리 단계다.
- Mattermost upstream과의 비교 가능성을 잃는 대규모 변경은 경계 결정 전 진행하지 않는다.
- 사용자가 보는 제품 표면을 우선 분리하고, 내부 compatibility layer는 필요한 만큼 유지한다.

View file

@ -0,0 +1,78 @@
# Milestone: 서버 코어 독립화 경계
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/independent-service/PHASE.md`
## 목표
Mattermost core에서 nexo가 계승할 메시징 기능과 제거, 숨김, 대체할 기능의 경계를 정한다.
이 결정은 서버 fork 비용과 upstream 추적 가능성에 직접 영향을 주므로 먼저 스케치로 유지한다.
## 상태
[스케치]
## 승격 조건
- [ ] nexo가 반드시 유지해야 할 core 기능 목록을 정한다.
- [ ] 제거하거나 숨길 Mattermost 기능 목록을 정한다.
- [ ] upstream merge 가능성을 유지할지, 독립 fork로 갈지 기준을 정한다.
- [ ] 서버 이미지 빌드 방식을 official image 사용, source build, custom image 중 하나로 결정한다.
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] Mattermost upstream 추적 가능성을 어느 정도까지 유지할지 결정한다.
- [ ] 웹앱을 유지할지, admin/debug 표면으로만 둘지, 제거할지 결정한다.
- [ ] nexo 서버 이미지를 언제 자체 빌드로 전환할지 결정한다.
## 범위
- `services/core` upstream baseline과 fork 전략
- server API, webapp, plugin, push-proxy의 유지/숨김/제거 후보
- Docker image build와 배포 전략 후보
- 불필요 기능 제거에 따른 테스트/운영 위험
## 기능
### Epic: [inheritance] 계승 경계
nexo가 Mattermost core에서 계속 가져갈 기능을 정의한다.
- [ ] [keep-list] 메시징, channel, user/session, push 관련 유지 기능 목록을 정리한다.
- [ ] [remove-list] nexo 목적과 맞지 않는 기능의 제거/숨김/보류 후보를 정리한다.
- [ ] [upstream-policy] upstream 추적 방식과 conflict 비용을 판단할 기준을 정리한다.
### Epic: [build] 서버 빌드
official image에서 custom image로 넘어갈 조건을 정리한다.
- [ ] [image-policy] official image, source build, custom image의 장단점과 전환 조건을 정리한다.
- [ ] [test-impact] server 변경 시 필요한 smoke, Go test, API test 범위를 정리한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- 실제 core 코드 제거와 대규모 rename은 승격 전까지 진행하지 않는다.
- upstream baseline 변경은 이 Milestone의 결정 없이 하지 않는다.
- full reimplementation은 기본 후보가 아니다.
## 작업 컨텍스트
- 관련 경로: `services/core/`, `services/core/UPSTREAM.md`, `services/core/compose/`
- 표준선(선택): 검증된 Mattermost core를 유지하면서 nexo 제품 표면부터 분리한다
- 선행 작업: 메시징 런타임 표준화
- 후속 작업: 제품화와 운영 모델
- 확인 필요: upstream 추적 정책, webapp 처리, server image 전환 시점

View file

@ -0,0 +1,79 @@
# Milestone: 제품화와 운영 모델
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/independent-service/PHASE.md`
## 목표
nexo를 단순 개발 레포가 아니라 반복 배포 가능한 서비스로 운영하기 위한 모델을 검토한다.
첫 운영 단위, 도메인/프록시, 환경 분리, 배포 검증, 앱 onboarding 문서를 정리할 준비를 한다.
## 상태
[스케치]
## 승격 조건
- [ ] 첫 production-like 환경의 범위를 정한다.
- [ ] 도메인, TLS, reverse proxy, 백업, 로그 보존의 최소 운영 기준을 정한다.
- [ ] 앱 onboarding 문서와 운영 runbook의 책임 경계를 정한다.
- [ ] release/versioning 기준을 정한다.
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] nexo를 먼저 private service로 운영할지, 여러 앱이 쓰는 internal platform으로 볼지 결정한다.
- [ ] release/versioning을 server, plugin, client 각각 따로 할지 monorepo tag로 묶을지 결정한다.
## 범위
- deployment topology 후보
- domain/proxy/TLS 후보
- backup/log/monitoring 최소 기준
- release/versioning 후보
- 앱 onboarding과 운영 runbook 후보
## 기능
### Epic: [deploy] 배포 모델
서비스로 운영할 최소 배포 단위를 정리한다.
- [ ] [topology] 단일 compose, remote docker, reverse proxy 연결 후보를 정리한다.
- [ ] [environment] dev/test/production-like 환경 분리 기준을 정리한다.
- [ ] [release] server/plugin/client 버전과 배포 순서를 정리한다.
### Epic: [ops] 운영 기준
서비스 운영에 필요한 최소 runbook 후보를 만든다.
- [ ] [health] core, db, push-proxy health check와 장애 확인 절차 후보를 정리한다.
- [ ] [backup] db와 runtime data 백업/복원 책임 후보를 정리한다.
- [ ] [onboarding] 새 앱이 nexo를 붙일 때 필요한 설정, credential, smoke 절차 후보를 정리한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- production hardening 구현은 승격 전까지 진행하지 않는다.
- 외부 공개용 landing page나 marketing site는 포함하지 않는다.
- billing, admin console, organization management는 별도 제품 결정 전까지 포함하지 않는다.
## 작업 컨텍스트
- 관련 경로: `services/core/compose/`, `docs/`, `packages/messaging_flutter/README.md`, `apps/client/README.md`
- 표준선(선택): 먼저 private/internal service 운영 기준을 잡고 확장 비용이 확인될 때 platform 형태를 검토한다
- 선행 작업: 서버 코어 독립화 경계, 멀티앱 채널 모델
- 후속 작업: 없음
- 확인 필요: 운영 제품 형태와 versioning 방식

View file

@ -0,0 +1,32 @@
# Phase: 메시징 런타임 표준화
## 상태
[계획]
## 목표
알림만 떼어낸 기능이 아니라, 여러 앱이 사용할 수 있는 메시징/알림 런타임 계약을 정리한다.
서버 core와 Flutter 플러그인의 역할을 명확히 나누고, 앱별 채널 분기와 호환 API를 제품 기능으로 다룰 수 있게 만든다.
## Milestone 흐름
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
- [계획] 메시징 계약 표준화
- 경로: `agent-ops/roadmap/phase/messaging-runtime/milestones/messaging-contract.md`
- 요약: 서버와 Flutter 플러그인이 공유할 메시징/알림 API, 이벤트, 저장 계약을 정리한다.
- [계획] 알림 파이프라인 고도화
- 경로: `agent-ops/roadmap/phase/messaging-runtime/milestones/notification-pipeline.md`
- 요약: FCM, ACK, inline reply, dismiss, open routing을 안정된 플러그인 책임으로 만든다.
- [스케치] 멀티앱 채널 모델
- 경로: `agent-ops/roadmap/phase/messaging-runtime/milestones/multi-app-channel.md`
- 요약: 추가 앱이 생길 때 사용 채널만 늘려 분기할 수 있는 서비스 모델을 검토한다.
## Phase 경계
- 계약이 중복되기 전까지 별도 `contract` 패키지를 만들지 않고, server API와 plugin public API 문서로 관리한다.
- `packages/messaging_flutter`는 앱별 알림 구현을 대체하는 공통 플러그인 책임을 가진다.
- `services/core`는 메시징 서버와 push-proxy 연동 책임을 가지며, client UI 책임을 갖지 않는다.

View file

@ -0,0 +1,75 @@
# Milestone: 메시징 계약 표준화
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/messaging-runtime/PHASE.md`
## 목표
서버 core와 Flutter 플러그인이 주고받는 메시지, 알림, device token, ACK, navigation event 계약을 정리한다.
초기에는 기존 Mattermost-compatible 계약을 유지하되, nexo가 소유할 API와 compatibility layer를 구분한다.
## 상태
[계획]
## 승격 조건
- 없음
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] nexo public API를 Mattermost-compatible 형태로 유지할지, nexo wrapper API를 먼저 만들지 결정한다.
- [ ] 메시징 전체 기능 중 Flutter 앱에 우선 노출할 범위를 결정한다.
## 범위
- Flutter plugin public Dart API
- Android native plugin event와 storage contract
- server core push payload, ACK, channel/thread routing contract
- 계약 문서 위치와 테스트 anchor
## 기능
### Epic: [api] Public API
앱이 의존할 수 있는 최소 메시징/알림 API 표면을 정리한다.
- [ ] [dart-api] Dart public API에서 유지할 이름, deprecated 후보, nexo wrapper 후보를 분리한다.
- [ ] [event-shape] notification event, opened event, token event의 payload shape와 backward compatibility 기준을 문서화한다.
- [ ] [token-flow] device token 저장, auth token 저장, signing key 저장 책임과 호출 순서를 정리한다.
### Epic: [server-contract] Server contract
서버 core와 플러그인이 공유하는 메시징/알림 계약을 확인 가능한 형태로 만든다.
- [ ] [push-payload] push payload 필드와 검증 기준을 서버/플러그인 양쪽 문서에서 연결한다.
- [ ] [ack-contract] ACK 요청 형식과 실패 처리 기준을 정리한다.
- [ ] [routing-contract] channel/thread navigation event가 client router로 전달되는 기준을 정리한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- API rename 구현은 이 Milestone의 문서/계약 정리 이후 별도 작업으로 진행한다.
- 별도 contract package 생성은 중복 비용이 확인되기 전까지 하지 않는다.
- full chat UI 구현은 이 Milestone의 범위가 아니다.
## 작업 컨텍스트
- 관련 경로: `packages/messaging_flutter/lib/`, `packages/messaging_flutter/android/`, `services/core/server/`, `apps/client/`
- 표준선(선택): compatibility를 깨는 rename보다 wrapper와 migration path를 우선 검토한다
- 선행 작업: 정체성 기준선, 클라이언트 검증 기준선
- 후속 작업: 알림 파이프라인 고도화, 멀티앱 채널 모델
- 확인 필요: public API 방향과 Flutter 앱 우선 노출 범위

View file

@ -0,0 +1,77 @@
# Milestone: 멀티앱 채널 모델
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/messaging-runtime/PHASE.md`
## 목표
여러 앱이 nexo를 사용할 때 서비스 전체를 복제하지 않고 앱별 사용 채널과 알림 라우팅만 늘릴 수 있는 모델을 검토한다.
이 Milestone은 아직 컨셉 단계이며, 앱 식별, 채널 분기, 권한, push credential 분리 기준을 먼저 정한다.
## 상태
[스케치]
## 승격 조건
- [ ] 첫 번째 외부 소비 앱 또는 내부 테스트 앱 후보를 정한다.
- [ ] 앱별 channel namespace, team/server 분리, tenant 분리 중 어떤 모델을 쓸지 결정한다.
- [ ] 앱별 push credential과 routing callback 분리 기준을 정한다.
- [ ] 구현 가능한 후속 Milestone을 API, server config, client integration 중 하나 이상으로 나눈다.
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] 앱별 분기를 channel 중심으로 둘지 tenant/server 중심으로 둘지 결정한다.
- [ ] 하나의 push-proxy credential을 공유할지 앱별 credential을 분리할지 결정한다.
## 범위
- 앱별 channel/tenant/server 분기 후보
- plugin configuration model 후보
- server core 설정과 push-proxy credential 분리 후보
- 첫 번째 소비 앱 onboarding 흐름
## 기능
### Epic: [model] 분기 모델
추가 앱이 생길 때 어떤 단위로 메시징 공간을 나눌지 후보를 정리한다.
- [ ] [channel-model] channel 중심 분기 모델의 장단점과 필요한 server/plugin 설정을 정리한다.
- [ ] [tenant-model] tenant/server 중심 분기 모델의 장단점과 운영 비용을 정리한다.
- [ ] [credential-model] push credential 공유/분리 후보와 위험을 정리한다.
### Epic: [onboarding] 앱 온보딩
새 앱이 nexo 메시징/알림을 붙일 때 필요한 최소 절차를 정의한다.
- [ ] [app-config] 앱이 넘겨야 할 server URL, auth token, signing key, routing callback 설정 후보를 정리한다.
- [ ] [smoke-flow] 새 앱 onboarding 후 확인해야 할 FCM, ACK, opened event smoke 흐름을 정리한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- 구체적인 멀티테넌시 구현은 승격 전까지 진행하지 않는다.
- 앱별 billing, admin UI, organization management는 포함하지 않는다.
- 기존 core의 team/channel 모델을 대체하지 않는다.
## 작업 컨텍스트
- 관련 경로: `services/core/`, `packages/messaging_flutter/`, `apps/client/`
- 표준선(선택): 먼저 channel 기반 최소 모델을 검토하고, 운영 비용이 커질 때 tenant/server 분리를 검토한다
- 선행 작업: 메시징 계약 표준화, 알림 파이프라인 고도화
- 후속 작업: 독립 서비스화 Phase의 운영 모델
- 확인 필요: 앱별 분기 단위와 credential 분리 기준

View file

@ -0,0 +1,76 @@
# Milestone: 알림 파이프라인 고도화
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/messaging-runtime/PHASE.md`
## 목표
FCM 수신부터 signing-key 검증, 로컬 저장, notification display, ACK, inline reply, dismiss, open routing까지 이어지는 알림 파이프라인을 플러그인 책임으로 안정화한다.
host app은 라우팅과 로그인 상태 연결만 담당하도록 경계를 유지한다.
## 상태
[계획]
## 승격 조건
- 없음
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] iOS/APNS 구현을 Android 안정화 이후로 미룰지, 같은 Phase에서 병행할지 결정한다.
- [ ] push ACK 실패와 offline queue를 어디까지 plugin 책임으로 볼지 결정한다.
## 범위
- Android FCM service와 notification helper
- signing key, auth token, device token storage
- ACK delivery, inline reply, dismiss action
- client notification-open callback
- 수동 smoke와 자동 테스트의 분리
## 기능
### Epic: [android-push] Android push
Android-first 알림 파이프라인을 안정된 제품 책임으로 만든다.
- [ ] [verify-payload] signing key 기반 payload 검증과 drop 조건을 테스트 가능한 형태로 유지한다.
- [ ] [display-notification] message/thread notification display 기준을 정리하고 회귀 테스트 후보를 만든다.
- [ ] [ack-delivery] ACK request 성공/실패 처리와 retry 후보를 정리한다.
- [ ] [reply-dismiss] inline reply와 dismiss action의 storage/network 경계를 정리한다.
### Epic: [host-routing] Host routing
host app이 받아야 할 최소 이벤트만 노출한다.
- [ ] [opened-event] notification-open event가 channel/thread routing으로 이어지는 기준을 유지한다.
- [ ] [host-contract] host app이 반드시 구현해야 할 callback과 login/logout hook을 문서화한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- full message composer나 chat screen UI 구현은 포함하지 않는다.
- APNS/iOS 구현은 결정 전까지 스캐폴드 유지로 둔다.
- 서버 core의 대규모 fork 변경은 포함하지 않는다.
## 작업 컨텍스트
- 관련 경로: `packages/messaging_flutter/android/`, `packages/messaging_flutter/lib/`, `apps/client/integration_test/`
- 표준선(선택): Android-first로 자동화 가능한 테스트를 늘리고, FCM delivery는 수동 smoke로 분리한다
- 선행 작업: 메시징 계약 표준화
- 후속 작업: 멀티앱 채널 모델, iOS/APNS 후보
- 확인 필요: iOS 우선순위와 ACK 실패 책임 범위

View file

@ -0,0 +1,33 @@
# Phase: 제품 기반 정리
## 상태
[진행중]
## 목표
nexo를 기존 기술명에 종속된 클론이 아니라 독립적인 메시징/알림 서비스로 정의한다.
모노레포 구조, core compose, client 검증 흐름, agent-ops 진입 규칙을 정리해 이후 기능 작업이 같은 기준선 위에서 진행되도록 만든다.
## Milestone 흐름
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
- [진행중] 정체성 기준선
- 경로: `agent-ops/roadmap/phase/product-foundation/milestones/identity-baseline.md`
- 요약: 제품 이름, 모노레포 경계, 기존 Mattermost/Flutter 의존 표면을 어떤 방식으로 다룰지 문서화한다.
- [계획] 운영 기준선
- 경로: `agent-ops/roadmap/phase/product-foundation/milestones/runtime-baseline.md`
- 요약: core compose, 원격 Docker 세팅, 환경 변수, 최소 health check를 안정된 기준선으로 만든다.
- [계획] 클라이언트 검증 기준선
- 경로: `agent-ops/roadmap/phase/product-foundation/milestones/client-validation.md`
- 요약: `apps/client`가 플러그인 소비 앱이자 테스트 호스트로 반복 검증을 제공하도록 고정한다.
## Phase 경계
- 모노레포의 기본 골격은 `apps/client`, `packages/messaging_flutter`, `services/core`로 유지한다.
- `contract`, `infra`, `sandbox` 같은 별도 최상위 모듈은 중복 필요가 명확해지기 전까지 만들지 않는다.
- Docker compose와 runtime 설정은 `services/core/compose/` 안에 둔다.
- `services/core/`의 upstream baseline 변경은 이 Phase의 기본 범위가 아니다.

View file

@ -0,0 +1,72 @@
# Milestone: 클라이언트 검증 기준선
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
## 목표
`apps/client`를 테스트용 앱이자 실제 소비 앱 형태의 얇은 클라이언트로 유지한다.
플러그인 등록, method channel, event channel, notification-open routing, Android native unit test를 반복 검증할 수 있게 한다.
## 상태
[계획]
## 승격 조건
- 없음
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- `apps/client`의 Flutter 테스트와 통합 테스트
- `packages/messaging_flutter`의 Dart 테스트와 Android native unit test
- Android SDK 또는 원격 Android 테스트 환경 사용 절차
- FCM/ACK 수동 smoke와 자동화 가능한 테스트의 경계
## 기능
### Epic: [test-host] 소비 앱 테스트 호스트
client 앱을 플러그인 통합 검증에 필요한 만큼만 유지한다.
- [ ] [thin-client] `apps/client`가 제품 UI가 아니라 plugin integration host 역할을 유지하도록 README와 테스트가 같은 기준을 따른다.
- [ ] [integration-path] plugin method channel, event channel, opened-routing 통합 테스트 경로를 유지한다. 검증: `cd apps/client && flutter test integration_test`가 지원 환경에서 성공한다.
- [ ] [native-test] Android native unit test 실행 절차를 유지한다. 검증: `cd apps/client/android && ./gradlew testDebugUnitTest`가 Android SDK 환경에서 성공한다.
### Epic: [manual-smoke] 외부 인프라 smoke
자동화하기 어려운 FCM과 서버 ACK 검증을 수동 체크로 분리한다.
- [ ] [fcm-manual] 실제 Firebase FCM delivery와 Mattermost-compatible ACK 검증 절차를 문서화한다.
- [ ] [remote-guide] 로컬 Android SDK가 없을 때 원격 테스트 환경 문서가 client README와 연결되도록 유지한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- client 앱을 별도 제품 UI나 sandbox 앱으로 확장하지 않는다.
- 플러그인 내부 동작을 client 앱에 복제하지 않는다.
- iOS/macOS push 구현은 이 Milestone의 범위가 아니다.
## 작업 컨텍스트
- 관련 경로: `apps/client/`, `packages/messaging_flutter/`, `packages/messaging_flutter/docs/android-test-environment.md`
- 표준선(선택): client는 실제 소비 앱 모양의 검증 호스트이며 별도 `/example`이나 `/sandbox`를 두지 않는다
- 선행 작업: client migration과 1차 테스트
- 후속 작업: 메시징 계약 표준화, 알림 파이프라인 고도화
- 확인 필요: 없음

View file

@ -0,0 +1,71 @@
# Milestone: 정체성 기준선
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
## 목표
이 Milestone은 nexo의 제품 정체성을 "Mattermost 클론"이 아니라 독립 메시징/알림 서비스로 고정한다.
기술적으로는 Mattermost 코어와 Flutter 플러그인을 활용하되, 문서와 작업 경계는 nexo 고유 서비스 기준으로 정리한다.
## 상태
[진행중]
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] `mattermost_push_plugin` public package name을 언제 nexo 계열 이름으로 바꿀지 결정한다.
- [ ] 외부 앱이 처음 붙을 때 nexo가 제공할 최소 제품 표면을 "알림 중심"으로 둘지 "메시징 전체"까지 열지 결정한다.
- [ ] 사용자에게 노출되는 Mattermost 관련 이름과 내부 호환 이름의 분리 기준을 결정한다.
## 범위
- 제품명 `nexo`와 모노레포 정체성 정리
- 기존 기술 의존 표면과 장기 독립화 방향 기록
- `agent-ops` 진입 규칙, README, roadmap 사이의 역할 분리
- 현재 구조에서 유지할 모듈 경계 정리
## 기능
### Epic: [identity] 제품 정체성
nexo가 제공하려는 서비스의 방향과 기존 기술을 대하는 방식을 문서 기준선으로 만든다.
- [ ] [product-story] nexo를 독립 메시징/알림 서비스로 설명하는 문서 표현을 README, roadmap, domain rule에서 일관되게 유지한다. 검증: 관련 문서에서 제품 목표와 모듈 경계가 충돌하지 않는다.
- [ ] [tech-boundary] Mattermost와 Flutter 관련 용어를 public product identity와 implementation detail로 구분하는 기준을 정리한다.
- [ ] [module-shape] 최상위 구조를 `apps/client`, `packages/messaging_flutter`, `services/core` 중심으로 유지하고 과한 scaffold를 만들지 않는 원칙을 문서화한다.
### Epic: [agent-entry] 작업 진입점
AI 에이전트와 사람이 같은 규칙으로 프로젝트에 들어오도록 작업 진입점을 고정한다.
- [ ] [rules-entry] `AGENTS.md`, `agent-ops/rules/project/rules.md`, domain rules, roadmap current의 역할을 충돌 없이 연결한다.
- [ ] [readme-entry] 루트 README가 제품 소개와 작업 진입점 역할을 함께 수행하도록 유지한다. 검증: README의 명령과 참조 경로가 실제 파일을 가리킨다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- 실제 package rename, import rename, native package rename은 이 Milestone에서 수행하지 않는다.
- 서버 코드에서 Mattermost 표면을 제거하는 작업은 독립 서비스화 Phase에서 다룬다.
- 별도 contract 패키지나 infra 모듈은 만들지 않는다.
## 작업 컨텍스트
- 관련 경로: `README.md`, `AGENTS.md`, `agent-ops/rules/project/rules.md`, `agent-ops/roadmap/`
- 표준선(선택): 제품명은 `nexo`, public plugin package name은 결정 전까지 `mattermost_push_plugin` 유지
- 선행 작업: 기존 monorepo migration과 README 보완
- 후속 작업: 운영 기준선, 메시징 계약 표준화
- 확인 필요: public package rename 시점과 사용자 노출 이름 분리 기준

View file

@ -0,0 +1,74 @@
# Milestone: 운영 기준선
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/product-foundation/PHASE.md`
## 목표
core compose와 원격 Docker 세팅을 nexo의 반복 가능한 테스트 런타임으로 고정한다.
기존 Mattermost 기반 서버를 유지하되 nexo용 포트, 환경 변수, 데이터 경로, push-proxy 설정을 명확히 분리한다.
## 상태
[계획]
## 승격 조건
- 없음
## 구현 잠금
- 상태: 잠금
- 결정 필요:
- [ ] 원격 환경에서 nexo를 별도 포트 테스트 서비스로 유지할지, 도메인/프록시까지 연결할지 결정한다.
- [ ] push-proxy의 FCM 자격 증명과 테스트/운영 credential 분리 기준을 결정한다.
## 범위
- `services/core/compose/`의 compose와 `.env.example`
- 원격 `~/docker/services/nexo/` 배치와 로컬 compose의 동등성
- core, Postgres, push-proxy 최소 health check
- runtime data와 secret이 git에 들어가지 않도록 유지하는 규칙
## 기능
### Epic: [compose] Core compose
local과 원격 Docker에서 같은 shape로 서버 런타임을 올릴 수 있게 한다.
- [ ] [local-compose] `services/core/compose`에서 core, db, push-proxy가 함께 실행되는 기준을 유지한다. 검증: `cd services/core/compose && docker compose up -d` 후 core ping이 성공한다.
- [ ] [remote-parity] 원격 `~/docker/services/nexo/compose`와 repo의 compose 파일이 의도적으로 동기화되는 절차를 문서화한다. 검증: local/remote compose와 `.env.example` hash 비교가 일치한다.
- [ ] [secret-boundary] `.env`, data, push-proxy credential이 git 추적 밖에 머무는 기준을 유지한다.
### Epic: [smoke] Runtime smoke
서버 런타임 변경 후 최소 확인 절차를 작게 유지한다.
- [ ] [health-check] core `/api/v4/system/ping` health check를 로컬과 원격에서 확인하는 절차를 문서화한다.
- [ ] [push-proxy-check] push-proxy가 core에서 참조 가능한 위치에 뜨는지 확인하는 smoke 기준을 정한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- nginx/domain 연결, TLS, production hardening은 이 Milestone의 필수 범위가 아니다.
- Mattermost 서버 이미지를 nexo 자체 빌드 이미지로 바꾸는 작업은 별도 결정 후 진행한다.
- 기존 운영 중인 다른 compose 서비스와의 병합은 이 Milestone에서 자동으로 하지 않는다.
## 작업 컨텍스트
- 관련 경로: `services/core/compose/`, `services/core/UPSTREAM.md`
- 표준선(선택): compose는 core service 내부에 두고, 별도 `infra/` 모듈을 만들지 않는다
- 선행 작업: core compose 원격 테스트 배치
- 후속 작업: 서버 커스터마이징 경계, 운영 모델
- 확인 필요: 원격 노출 방식과 push credential 분리 방식

View 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>**: <어디까지가 도메인이고 어디서부터 도메인인지>
## 금지 사항
- < 도메인 코드에서 하면 되는 >

View file

@ -0,0 +1,97 @@
# Agent-Ops 철학
이 문서는 agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 읽는다.
일반 구현 작업에서는 읽지 않는다.
## 핵심
- agent-ops는 AI agent가 작업하기 위한 규칙이자 가이드다.
- 사람 문서처럼 장황하게 설명하지 않고, agent가 바로 실행할 수 있게 작성한다.
- 필요한 컨텍스트만 읽게 만든다. 모든 문서를 항상 읽게 만들지 않는다.
- 애매한 형식을 만들지 않는다. 경로, 상태, id, 입력, 출력은 판별 가능해야 한다.
- 문서는 짧고 단단해야 한다. 길어서 이해되는 문서보다 짧아서 헷갈리지 않는 문서가 낫다.
## 문서 작성
- 규칙과 스킬은 핵심만 쓴다.
- 같은 말을 여러 문서에 반복하지 않는다. 한 곳에 두고 링크한다.
- 설명보다 조건, 입력, 행동, 금지 사항을 우선한다.
- "적절히", "필요하면", "가능하면" 같은 말은 판별 기준이 없으면 쓰지 않는다.
- 예외가 있으면 예외 조건을 같이 쓴다.
- 긴 배경 설명은 README나 별도 참조 문서로 보내고, 실행 문서에는 실행 규칙만 남긴다.
- 룰 문서는 협업자가 직접 읽는 계약 문서이므로 한국어 `한다`체로 작성한다.
- README, GUIDE, roadmap 문서는 사람이 함께 검토하는 협업 문서이므로 한국어 설명체 또는 존댓말을 사용할 수 있다.
- 스킬 문서는 실행 안정성을 우선한다. 한국어 또는 영어를 사용할 수 있고, 이미 잘 동작하는 절차 계약은 언어 통일만을 위해 수정하지 않는다.
- path, filename, 상태값, id, regex, command, frontmatter key, runtime protocol token은 원문 ASCII 식별자를 유지한다.
## 라우팅
- 라우팅은 얕아야 한다.
- 1홉은 진입 파일에서 공통/프로젝트 규칙을 읽는 단계다.
- 2홉은 규칙에서 domain rule, roadmap rule, router를 따라가는 단계다.
- 3홉은 router에서 SKILL.md를 읽는 단계다.
- 4홉은 skill이 템플릿이나 참조 문서를 추가로 읽는 단계다.
- 4홉 이상이 필요하면 구조가 과하게 쪼개졌는지 먼저 의심한다. 필요하면 앞 문서에 바로 가는 링크를 추가한다.
- 깊은 링크 체인을 만들지 않고, 필요한 문서가 무엇인지 앞 문서에서 바로 보이게 한다.
- 일반 작업마다 router, 모든 skill, 전체 roadmap, archive를 읽게 만들지 않는다.
## LLM과 런타임
- LLM은 의미 판단, 범위 판단, 요약, 설계 선택을 맡는다.
- 런타임은 파일명, 폴더명, 상태값, exit code처럼 결정적으로 판별 가능한 일을 맡는다.
- LLM 없이 처리할 수 있는 구간은 파일 규약으로 뺀다.
- 런타임 신호는 문서 본문보다 경로와 이름에 둔다.
- 런타임 신호를 만들 때는 agent가 본문을 읽지 않아도 판별 가능해야 한다.
- `m-<milestone-slug>` 같은 prefix는 런타임 판별을 위한 신호다.
- code-review는 PASS 산출물을 만들고 완료 이벤트 메타데이터를 남긴다.
- roadmap 반영 여부와 호출 타이밍은 런타임이 완료 이벤트를 보고 판단한다.
## 스킬 그룹 경계
- 스킬 그룹은 자기 라이프사이클 안에서만 강한 계약을 가진다.
- 스킬 그룹끼리는 다른 그룹의 내부 절차를 자동 호출하거나 전제하지 않는다.
- 그룹 간 연결은 사용자 명령, 런타임 이벤트, 또는 판별 가능한 파일 상태로만 한다.
- 구현 작업 그룹은 `plan``code-review`의 PLAN/CODE_REVIEW 루프를 소유한다.
- 로드맵 그룹은 `create-roadmap``update-roadmap`의 Phase/Milestone 상태, 구현 잠금, archive 흐름을 소유한다.
- `code-review`가 남긴 PASS 완료 이벤트를 로드맵에 반영할지, 언제 반영할지는 런타임이 판단하고 `update-roadmap` 흐름으로 넘긴다.
- cross-project 잠금이나 `.agent-roadmap-sync` 같은 workspace-level 상태는 로드맵 그룹과 런타임의 책임이다. `plan``code-review`에 의존성 동기화 규칙을 넣지 않는다.
- 새 스킬을 만들기 전에 기존 그룹의 자연스러운 입력, 상태 전환, 후처리 지점에 넣을 수 있는지 먼저 본다. 다만 다른 그룹 경계를 침범해야 하면 런타임 이벤트로 분리한다.
## 로드맵
- roadmap은 장기 기억이고, agent-task는 실행 상태다.
- current는 현재 작업 하나가 아니라 활성 Phase/Milestone 후보 창이다.
- Phase와 Milestone은 큰 방향과 기능 단위를 담는다.
- 구현 계획은 agent-task의 PLAN/CODE_REVIEW 루프에 둔다.
- 완료 후보는 바로 archive하지 말고 `[검토중]`으로 둔다.
- archive는 일반 작업에서 읽지 않는다. 과거 근거가 필요할 때만 링크를 따라 읽는다.
## 스킬
- skill은 절차 문서다.
- skill 하나에 책임 하나만 둔다.
- skill이 다른 skill을 자동으로 깊게 호출하는 구조를 만들지 않는다.
- skill 본문은 실행에 필요한 규칙만 둔다.
- 템플릿은 출력 형식이 흔들릴 때만 둔다.
- 스킬 업데이트 시 router, rules, template, 출력 형식이 같은 계약을 말하는지 같이 확인한다.
- plan과 code-review처럼 짝 계약을 양쪽에서 반복해 강제하는 구조는 의도된 중복으로 본다. 동작 중인 짝 계약은 일관성 정리만을 위해 합치지 않는다.
## 좋은 구조
- 진입 파일은 최소 규칙만 둔다.
- common rules는 공통 시작점만 둔다.
- project rules는 프로젝트 특화 판단만 둔다.
- domain rules는 특정 코드 영역 규칙만 둔다.
- skills는 반복 작업 절차만 둔다.
- roadmap은 장기 목표와 기능 단위만 둔다.
- agent-task는 실행 중인 작업 상태와 완료 산출물만 둔다.
## 경고 신호
- 같은 내용을 세 군데 이상 설명하고 있다.
- 어떤 문서를 읽어야 할지 문서 안에서 다시 찾아야 한다.
- 상태값이 사람은 이해하지만 런타임은 판별하기 어렵다.
- skill이 너무 많은 예외를 품고 있다.
- README가 내부 규칙 문서처럼 길어지고 있다.
- archive를 일반 작업 컨텍스트로 끌어오고 있다.
- LLM이 파일명만 봐도 될 일을 본문까지 읽어 판단하고 있다.

View file

@ -0,0 +1,120 @@
# 로드맵 규칙
`agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서만 적용한다.
## 구조
- 최상위 로드맵은 `agent-ops/roadmap/ROADMAP.md`다.
- 활성 Phase는 `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`에 둔다.
- 활성 Milestone은 해당 Phase 아래 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에 둔다.
- `<phase-slug>``<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용한다.
- 완료된 Phase는 scaffold 그대로 `agent-ops/roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 `archive/phase/<phase-slug>/milestones/` 아래에 둔다.
- 진행중 Phase 안에서 완료된 Milestone은 활성 `PHASE.md`에 짧은 archive 링크를 남기고, 상세 문서는 `agent-ops/roadmap/archive/phase/<phase-slug>/milestones/`로 이동한다.
- archive `PHASE.md`는 Phase 자체가 완료/폐기될 때만 만들며, 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
## 로딩
- 세션 최초 1회 `agent-ops/roadmap/current.md`를 읽고 활성 Phase, 활성 Milestone의 이름, 경로, 선택 규칙만 짧게 기억한다.
- 일반 작업에서는 `ROADMAP.md`를 읽지 않는다.
- 일반 작업에서는 `agent-ops/roadmap/archive/**`를 읽지 않는다.
- 기능 추가, 구조 변경, 구현 계획 전에는 요청과 변경 파일에 맞는 활성 Phase와 활성 Milestone 문서를 읽는다.
- 로드맵 현지점 확인은 `current.md`, `ROADMAP.md`의 Phase 흐름, 활성 `PHASE.md`의 Milestone 흐름, 활성 Milestone의 제목/목표/상태만 기본으로 읽는다.
- `ROADMAP.md`는 로드맵 생성/갱신, Phase 추가/삭제/전환, 전체 구조 변경, 활성 범위 밖 작업 확인 때만 읽는다.
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 필요한 archive 문서만 읽는다.
## Phase와 Milestone 선택
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 Milestone 후보 목록이다.
- 활성 Phase는 `agent-ops/roadmap/phase/**/PHASE.md`만 대상으로 한다.
- 활성 Milestone은 `agent-ops/roadmap/phase/**/milestones/*.md`만 대상으로 한다.
- `current.md`에는 `[완료]` 또는 `[폐기]` Phase/Milestone을 남기지 않는다. 완료 후보는 승인 전까지 `[검토중]`으로 둔다.
- "로드맵에 추가", "마일스톤에 추가"처럼 target 없는 신규 작업 추가 요청은 `update-roadmap` 스킬로 처리하고, Phase/Milestone/Epic/Task 배치를 자동 판단한다.
- target 없는 신규 추가 요청은 먼저 요청 규모를 `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 단위로 판정한다.
- target 없는 신규 추가 요청은 활성 창만으로 결정하지 말고 필요한 경우 `ROADMAP.md`의 Phase 흐름과 관련 Phase/Milestone 문서를 비교한다.
- 배치는 Phase -> Milestone -> Epic -> Task 순서로 내려가며 같은 레벨의 동일/유사 후보를 먼저 찾는다.
- 동일/유사 항목이 이미 있으면 새로 만들지 말고 기존 항목을 업데이트한다.
- 적절한 기존 후보가 없을 때만 판정한 규모에 맞는 새 항목을 만든다.
- 부모 후보는 있고 판정 규모의 항목만 없으면 부모 아래에 새 항목을 만들고, 부모도 없을 때만 필요한 부모 항목을 함께 만든다.
- 자동 배치할 때는 선택한 Phase/Milestone/Epic/Task와 밀린 후보의 이유를 결과에 남긴다.
- `current.md`가 아카이브 경로를 가리키면 해당 항목은 활성 후보로 읽지 말고 로드맵 갱신이 필요하다고 보고한다.
- 선택한 Phase/Milestone의 목표 또는 범위 제외와 요청이 충돌하면 구현 전에 사용자에게 확인한다.
## 상태 표기
- Phase와 Milestone 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 `agent-task` 구현 계획 생성과 코드 구현을 시작하지 않는다.
- `[스케치]` 항목은 `[계획]`으로 승격하기 위한 `승격 조건`, 사용자 결정, 범위 경계, 후속 Milestone 후보를 정리하는 것이 목적이다.
- `[계획]` 이상 상태의 Milestone에서 `승격 조건` 섹션은 선택 사항이다. 섹션이 없거나 `- 없음`이면 템플릿 오류로 보지 않는다.
- `[스케치]``[계획]`으로 전환하려면 `승격 조건`의 미정 항목이 해소되고, 목표, 범위, 기능 Task, 직접적인 사용자 결정 항목, 후속 구현 단위가 구현 계획을 만들 수 있을 만큼 정리되어야 한다.
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 정리되어 구현 계획을 만들 수 있는 상태다.
- 갱신 범위에 포함된 기존 진행 상태 표기는 `[진행중]`으로 정리한다.
- `[검토중]`은 모든 기능 Task와 Task 안에 명시된 검증이 충족된 것으로 보이나, 사용자의 최종 완료 확인과 archive 승인이 아직 남은 완료 후보 상태다.
- `[검토중]` 항목은 활성 경로에 남기고 `current.md`의 활성 후보로 유지할 수 있다.
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
## 구현 잠금
- `구현 잠금`은 승인 의식이 아니라 사용자 결정이 필요한지 표시하는 얇은 상태다.
- 제품 방향, 범위, 우선순위, 책임 경계처럼 사용자만 결정할 수 있는 항목이 남아 있으면 상태를 `잠금`으로 두고 `결정 필요` 체크리스트에 질문을 적는다.
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선이나 구현 가정으로 기록한다.
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
- 선택한 Milestone에 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 사용자에게 확인한다.
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 표준선으로 처리 가능한 작업을 막지 않는다.
- 잠금 상태를 바꾸더라도 `기능` Task를 자동 완료 처리하지 않는다.
- `[스케치]` 상태의 Milestone은 `구현 잠금``해제`로 보이더라도 구현 계획과 코드 구현 대상이 아니다. 먼저 `[계획]`으로 승격해야 한다.
## Epic과 Task id
- Milestone 문서의 실행 체크리스트는 `기능` 섹션 하나로 작성한다. 새 Milestone이나 갱신 범위에 포함된 Milestone에는 별도 `완료 기준` 섹션을 만들지 않는다.
- 기존 Milestone에 `필수 기능``완료 기준`이 분리되어 있으면, 갱신 시 `완료 기준`을 관련 기능 Task 안의 선택적 `검증:` 문구로 흡수하고 섹션을 제거한다.
- 기능 Task는 기능 또는 산출물 단위다. 검증이 필요한 기능만 같은 Task 안에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
- 검증이 명시된 Task의 `[x]`는 기능/산출물과 해당 검증이 모두 충족되었다는 뜻이다. 검증이 명시되지 않은 Task의 `[x]`는 기능/산출물 완료 근거가 충분하다는 뜻이다.
- 사용자만 결정할 수 있는 검토/선택/우선순위 항목은 기능 Task로 쓰지 않는다. `구현 잠금``결정 필요` 또는 `작업 컨텍스트`로 분리하고, 현재 구현에 직접 필요하면 plan 생성 전에 사용자 확인을 받는다.
- `기능` 섹션의 Task 체크리스트는 Epic 바로 아래의 flat list를 기본으로 한다. 구현 세부, 테스트만 따로 떼어낸 하위 체크박스는 roadmap에 만들지 말고 plan 내부 체크리스트나 같은 Task의 `검증:`으로 흡수한다.
- Epic heading은 `### Epic: [epic-id] <이름>` 형식을 사용한다.
- Task는 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식을 사용한다.
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 `-`, `_`, `+`, `=`만 사용한다. 가능하면 1~3 segment를 우선하며, 전체 길이는 32자 이하를 권장한다.
- epic-id와 item-id는 해당 Milestone 안에서만 유일하면 된다.
- 다른 Milestone에서는 같은 id를 다시 사용할 수 있다. 여러 Milestone 후보에서 같은 id가 발견되면 Milestone 이름이나 문서 경로로 대상을 확정한다.
- 사용자가 epic-id 또는 item-id를 언급하면 해당 Milestone의 Epic/Task 항목을 우선 anchor로 삼고, 기존 id는 명시적 요청 없이 바꾸지 않는다.
## Milestone 기반 agent-task
- `plan` 스킬이 활성 Milestone 범위의 구현 계획을 만들면 task group은 `agent-task/m-<milestone-slug>/` 형식을 사용한다.
- `<milestone-slug>`는 활성 Milestone 파일명에서 `.md`를 제거한 값이며, Phase slug, Epic id, Task id, 별도 task slug를 task group에 넣지 않는다.
- split 작업은 기존 규칙 그대로 `agent-task/m-<milestone-slug>/<subtask_dir>/` 아래에 둔다.
- `m-<milestone-slug>`는 Milestone 기반 작업 전용 예약 prefix이며, 일반 작업 task group은 `m-`으로 시작하지 않는다.
- 런타임은 파일 내부가 아니라 task group 이름만으로 Milestone 기반 작업 여부를 판별한다.
- `code-review`에서 `m-<milestone-slug>` 작업이 PASS되면 roadmap을 직접 수정하거나 `update-roadmap`을 직접 호출하지 않는다.
- 런타임은 PASS 완료 이벤트의 task group에서 `m-<milestone-slug>`를 판별하고, 상태 체크 후 `update-roadmap` 흐름으로 Milestone 업데이트를 호출한다.
- 런타임 완료 이벤트가 최종 archive 경로만 갖고 있으면 `agent-task/archive/YYYY/MM/m-<milestone-slug>/...``agent-task/m-<milestone-slug>/...` 형태의 `origin-task`로 정규화해 전달한다.
- 런타임 호출에서 매칭되는 활성 Milestone이 없거나 둘 이상이면 추정하지 말고 수동 target 선택이 필요하다고 보고한다.
- `WARN` 또는 `FAIL`은 Milestone 완료 업데이트를 하지 않는다. 일반적으로 같은 `m-<milestone-slug>` task group에서 follow-up plan/review를 이어가지만, code-review의 user-review gate가 트리거되면 `USER_REVIEW.md`를 남기고 사용자 판단을 기다린다.
- `[스케치]` Milestone은 Milestone 기반 `agent-task` 생성 대상이 아니다. 런타임이나 plan 스킬은 이를 구현 작업으로 라우팅하지 않고 `[계획]` 승격 필요를 보고한다.
## 완료 리뷰
- Task 완료나 Milestone 갱신 시 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`가 되었는지 확인한다.
- 모두 충족된 것으로 보이면 Milestone을 `[완료]`로 바로 바꾸거나 archive로 이동하지 말고 `[검토중]`으로 바꾼다.
- `[검토중]`으로 바꿀 때는 Milestone 문서에 `완료 리뷰` 섹션을 만들거나 갱신하고, 완료 근거 1~3줄과 사용자에게 필요한 최종 확인 항목을 남긴다.
- 사용자가 완료를 승인한 뒤에만 `[완료]`로 전환하고 archive 이동을 수행한다.
- Phase도 모든 하위 Milestone이 `[완료]` 또는 `[폐기]`로 정리되어 Phase 완료 후보가 되면 `[검토중]`으로 두고 사용자 최종 확인을 받은 뒤 `[완료]` 또는 `[폐기]`로 전환한다.
## 로드맵 현지점
- 현재 작업 지점이나 로드맵상 현 위치 확인 요청은 `analyze-roadmap-position` 스킬로 처리한다.
- 답변은 `agent-ops/skills/common/_templates/roadmap-position-report-template.md` 섹션과 필드 순서를 따른다.
- 기본 동작에서는 코드, git 상태, diff를 읽지 않고 `로드맵 > Phase > Milestone` breadcrumb와 흐름 목록으로 현재 좌표를 보여준다.
- current가 Phase 또는 Milestone 후보를 여럿 가리키면 모두 `현재 후보`로 표시하고 짧은 역할 태그만 붙인다.
## 아카이브
- 완료 또는 폐기되어 현재 작업 후보에서 제외할 Phase/Milestone은 `update-roadmap` 스킬로 아카이빙한다.
- `[검토중]` Phase/Milestone은 archive 대상이 아니며, 사용자 승인 전까지 활성 경로에 남긴다.
- Phase 아카이브 대상은 `agent-ops/roadmap/archive/phase/<phase-slug>/PHASE.md`와 같은 scaffold로 이동한다.
- Milestone 아카이브 대상은 `agent-ops/roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동한다.
- 아카이빙할 때는 활성 `ROADMAP.md` 또는 활성 `PHASE.md`에 archive 문서 링크와 짧은 요약만 남긴다.
- 아카이브된 Phase/Milestone은 `current.md`에 남기지 않고, 일반 Phase/Milestone 선택이나 위치 분석의 후보로 삼지 않는다.
- 아카이브 문서는 과거 기록 스냅샷으로 보고, 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.

View file

@ -0,0 +1,30 @@
# 공통 규칙
- **현재 문서를 반드시 끝까지 정독하고 작업한다. 다 읽지 않고 즉각 작업은 금지한다.**
- 기존 구조를 우선한다. 새 파일 생성보다 기존 파일 수정을 우선한다.
- 코드 변경 전 관련 domain rule을 먼저 확인한다.
- 요청 범위를 넘는 변경을 하지 않는다.
- 불확실하면 단정하지 말고 후보를 제시한다.
- `agent-task/archive/**`는 사용자가 명시적으로 요청한 경우에만 읽는다.
- `agent-ops/roadmap/` 디렉터리가 있는 프로젝트에서도 `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 로드맵 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `agent-ops/rules/common/rules-roadmap.md`의 archive 접근 규칙을 따른다.
- agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다.
**세션 최초 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 업데이트 / 진입 파일 재적용

View file

@ -0,0 +1,50 @@
---
domain: client-app
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
---
# client-app
## 목적 / 책임
Flutter 클라이언트와 `mattermost_push_plugin`의 독립 소비 앱, 통합 테스트 호스트를 담당한다. 실제 제품 앱으로 확장되기 전에도 plugin integration이 깨지지 않는지 확인하는 기준점이다.
## 포함 경로
- `apps/client/lib/` — Flutter app source
- `apps/client/test/` — widget/unit tests
- `apps/client/integration_test/` — plugin integration tests
- `apps/client/android/`, `apps/client/ios/`, `apps/client/macos/` — host app platform configuration
- `apps/client/pubspec.yaml` — app dependency and Flutter metadata
## 제외 경로
- `packages/messaging_flutter/` — push plugin 내부 구현 책임
- `services/core/` — messaging server runtime 책임
- `docs/`, `bin/` — workspace 공통 문서와 command 책임
## 주요 구성 요소
- `MyApp` — plugin event stream과 navigation callback을 표시하는 host app shell
- `MattermostPushPlugin.instance` — app이 소비하는 plugin singleton
- `plugin_integration_test.dart` — plugin integration behavior 검증 진입점
## 유지할 패턴
- plugin dependency는 workspace path dependency `../../packages/messaging_flutter`를 사용한다.
- 앱에서는 token, notification, opened event, navigation callback 등 host integration만 검증한다.
- plugin 내부 native push 처리나 storage 로직을 앱으로 복제하지 않는다.
- Flutter check는 `bin/test`, `bin/lint`, 필요 시 `flutter test integration_test` 흐름을 따른다.
## 다른 도메인과의 경계
- **messaging-flutter**: app은 plugin API 소비자이고, push 처리의 source of truth는 plugin이다.
- **core-service**: server runtime이 필요한 테스트는 명시적으로 compose 또는 별도 환경을 켠 뒤 수행한다.
- **workspace-ops**: workspace command가 client 검증을 호출하지만 app 구조와 host behavior는 이 도메인이 소유한다.
## 금지 사항
- 플러그인 버그를 우회하기 위해 app에 duplicate push 처리 경로를 만들지 않는다.
- generated Flutter platform 파일을 불필요하게 재생성하거나 대량 변경하지 않는다.
- 앱 검증 목적을 넘는 제품 기능을 사용자 요청 없이 크게 확장하지 않는다.

View file

@ -0,0 +1,52 @@
---
domain: core-service
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
---
# core-service
## 목적 / 책임
Mattermost 기반 메시징 서버 코어와 관련 웹앱, API 문서, 로컬 compose 실행 환경을 담당한다. upstream baseline과 비교 가능한 상태를 유지하는 것이 중요하다.
## 포함 경로
- `services/core/server/` — Go 기반 Mattermost server module
- `services/core/webapp/` — Mattermost webapp, platform packages, frontend tooling
- `services/core/api/` — API reference tooling
- `services/core/compose/` — local core runtime Docker Compose
- `services/core/e2e-tests/`, `services/core/tools/` — core 검증 및 보조 도구
- `services/core/UPSTREAM.md` — upstream baseline 기록
## 제외 경로
- `packages/messaging_flutter/` — Flutter push plugin 책임
- `apps/client/` — plugin consumer app 및 integration host 책임
- `docs/`, `bin/` — 워크스페이스 공통 운영 문서와 entrypoint 책임
## 주요 구성 요소
- `services/core/server/go.mod` — Mattermost server Go module 기준
- `services/core/webapp/package.json` — webapp npm workspace 기준
- `services/core/api/package.json` — API reference tooling 기준
- `services/core/compose/docker-compose.yml` — local core 서비스 구성
## 유지할 패턴
- Mattermost upstream에서 온 구조와 명명은 필요한 경우에만 변경한다.
- 제품 특화 변경은 좁은 파일 범위로 유지하고, upstream 재동기화를 방해하지 않게 설명 가능한 단위로 남긴다.
- Go 검증은 기본 `bin/test`에서 skip되며, 필요할 때 `NEXO_CORE_GO_TEST=1` 등 명시적 플래그로 실행한다.
- webapp 변경은 기존 npm workspace와 package script를 따른다.
## 다른 도메인과의 경계
- **messaging-flutter**: server는 push payload와 ACK endpoint 성격을 제공하고, native 알림 표시와 device token 저장은 plugin이 담당한다.
- **client-app**: server runtime과 client host 검증은 분리한다. client app에서 server 내부 코드를 직접 수정하지 않는다.
- **workspace-ops**: 공통 실행 스크립트가 core 명령을 호출할 수 있지만 core 내부 정책은 이 도메인이 소유한다.
## 금지 사항
- `services/core/UPSTREAM.md` baseline을 근거 없이 변경하지 않는다.
- 대량 rename, formatting-only churn, upstream 파일의 광범위 재배치를 작업 범위 없이 수행하지 않는다.
- generated/build/cache 산출물을 소스 변경처럼 다루지 않는다.

View file

@ -0,0 +1,53 @@
---
domain: messaging-flutter
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
---
# messaging-flutter
## 목적 / 책임
Mattermost 호환 푸시 알림 Flutter 플러그인을 담당한다. FCM 수신, 알림 표시, tap/open 이벤트, inline reply, dismiss 처리, ACK 전달, token/key 저장을 앱별 구현으로 흩어지지 않게 모은다.
## 포함 경로
- `packages/messaging_flutter/lib/` — public Dart API와 Flutter-facing behavior
- `packages/messaging_flutter/android/` — Android native plugin implementation
- `packages/messaging_flutter/ios/`, `packages/messaging_flutter/macos/` — platform scaffold와 stub
- `packages/messaging_flutter/test/` — Dart API contract tests
- `packages/messaging_flutter/docs/` — plugin 개발 및 검증 문서
- `packages/messaging_flutter/pubspec.yaml` — plugin package metadata
## 제외 경로
- `apps/client/` — plugin을 소비하는 host app 책임
- `services/core/` — server, webapp, API, compose runtime 책임
- root `bin/` — workspace-level command entrypoint 책임
## 주요 구성 요소
- `MattermostPushPlugin` — singleton public API, event stream, token/key action channel
- `NotificationOpenedEvent` — notification open payload parsing
- `MattermostFirebaseMessagingService` — Android FCM 수신 진입점
- `NotificationReplyBroadcastReceiver`, `NotificationDismissService` — Android action handling
- `ReceiptDelivery` — ACK delivery 책임
## 유지할 패턴
- public import는 `package:mattermost_push_plugin/mattermost_push_plugin.dart` 경로를 유지한다.
- Android가 production target이며 iOS/macOS는 stub 상태임을 명확히 보고한다.
- host app이 해야 할 Firebase 초기화, token 등록, navigation 연결은 README의 Host App Responsibilities와 맞춘다.
- native event type은 Dart API의 `PushNotificationType`과 호환되게 유지한다.
## 다른 도메인과의 경계
- **client-app**: client app은 integration host이며 plugin 내부 push 처리 로직을 복제하지 않는다.
- **core-service**: server와의 계약은 payload, signing key, auth token, ACK/reply endpoint 수준으로 다룬다.
- **workspace-ops**: 공통 `bin/test`, `bin/lint`가 plugin 검증을 호출하지만 plugin 세부 검증 기준은 이 도메인이 소유한다.
## 금지 사항
- package rename이나 public API breaking change를 사용자 결정 없이 수행하지 않는다.
- host app 전용 navigation, 화면 구성, 제품 UI 상태를 plugin 내부에 넣지 않는다.
- iOS/macOS stub을 production-ready로 단정하지 않는다.

View file

@ -0,0 +1,52 @@
---
domain: workspace-ops
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
---
# workspace-ops
## 목적 / 책임
워크스페이스 공통 문서, helper command, 루트 수준 설정을 담당한다. 여러 모듈에 걸친 작업 흐름을 연결하되 각 모듈의 내부 책임을 침범하지 않는다.
## 포함 경로
- `bin/` — root helper entrypoints: `dev`, `test`, `lint`, `build`
- `docs/` — 여러 모듈에 걸친 제품, migration, 운영 문서
- `README.md` — workspace overview
- root `.gitignore`와 루트 수준 설정 파일
- `agent-ops/rules/project/**`, `agent-ops/skills/project/**` — 프로젝트 전용 agent-ops 규칙과 skill
## 제외 경로
- `services/core/` — core server, webapp, API 구현 책임
- `packages/messaging_flutter/` — Flutter push plugin 구현 책임
- `apps/client/` — client host app 구현 책임
- `agent-ops/rules/common/**`, `agent-ops/skills/common/**` — 공통 framework 파일이며 프로젝트에서 직접 수정하지 않는다.
## 주요 구성 요소
- `bin/test` — Flutter tests와 선택적 Go test 실행
- `bin/lint` — Flutter analyze와 선택적 Go vet 실행
- `bin/build` — Flutter web build와 선택적 Go build 실행
- `bin/dev` — 개발 entrypoint 안내
## 유지할 패턴
- root helper script는 모듈별 command를 얇게 묶는 역할로 유지한다.
- 로컬 도구가 없을 때 skip하는 기존 동작을 보존하고, skip된 검증은 작업 보고에 명시한다.
- 여러 모듈에 걸친 문서는 `docs/`에 두고, 모듈 내부만 해당하는 설명은 해당 모듈 README나 docs에 둔다.
- 프로젝트 전용 agent-ops 파일만 수정하고 common 파일은 원본 framework에서 동기화한다.
## 다른 도메인과의 경계
- **core-service**: workspace script가 core 검증을 호출할 수 있지만 core 내부 명령 선택은 core 규칙을 따른다.
- **messaging-flutter**: plugin 검증은 workspace script로 실행할 수 있으나 API/플랫폼 계약은 plugin 도메인이 소유한다.
- **client-app**: client 검증은 workspace script로 실행할 수 있으나 app behavior는 client 도메인이 소유한다.
## 금지 사항
- root helper에 모듈 내부 business logic을 넣지 않는다.
- module-specific 문서를 이유 없이 root docs로 끌어올리지 않는다.
- `agent-ops` common 파일을 타겟 프로젝트에서 직접 편집하지 않는다.

View file

@ -0,0 +1,60 @@
# nexo 프로젝트 규칙
## 응답 언어
- 기본 응답은 한국어로 작성한다.
- 파일명, 명령어, 패키지명, API 이름, 코드 식별자는 원문 그대로 유지한다.
## 프로젝트 개요
`nexo`는 메시징 서버, Flutter 클라이언트, Flutter 푸시 알림 패키지를 한 워크스페이스에서 함께 관리하는 프로젝트다.
주요 경계는 다음과 같다.
- `services/core/` — Mattermost `v11.4.2` 기반 메시징 서버 코어, 웹앱, API 문서, compose 환경
- `packages/messaging_flutter/` — Mattermost 호환 푸시 알림 Flutter 플러그인
- `apps/client/` — 플러그인을 검증하는 Flutter 클라이언트와 통합 테스트 호스트
- `docs/`, `bin/` — 워크스페이스 공통 문서와 helper entrypoint
## 기술 스택
- Flutter / Dart `sdk: ^3.11.3`
- Android native plugin: Kotlin, Java, Gradle
- iOS / macOS plugin scaffold: Swift
- Server core: Go `1.24.13`, Mattermost server module
- Webapp / API tooling: Node.js, npm workspaces, TypeScript, Redocly
- Local runtime: Docker Compose under `services/core/compose/`
## 작업 원칙
- `services/core/`는 Mattermost upstream fork 성격이 강하므로 제품 특화 변경은 작고 비교 가능하게 유지한다.
- `services/core/UPSTREAM.md`의 baseline 정보를 임의로 바꾸지 않는다.
- Flutter 플러그인의 public package name은 현재 `mattermost_push_plugin`이며, 소비 앱과 호환성이 걸려 있으므로 rename은 별도 결정 없이 하지 않는다.
- 푸시 알림 처리 책임은 `packages/messaging_flutter/`에 두고, `apps/client/`에는 검증과 host integration만 둔다.
- `apps/client/`는 독립 소비 앱 역할을 하므로 플러그인 내부 동작을 복제하지 않는다.
- `build/`, `.dart_tool/`, Android/iOS/macOS 생성물, upstream bulk 파일은 요청 범위 밖이면 건드리지 않는다.
- 모듈별 README가 있는 경우 해당 모듈 안의 설명을 우선한다.
## 검증 명령
- 전체 기본 검증: `bin/test`
- 전체 lint: `bin/lint`
- 전체 build: `bin/build`
- 서버 Go test: `NEXO_CORE_GO_TEST=1 bin/test`
- 서버 Go vet: `NEXO_CORE_GO_LINT=1 bin/lint`
- 서버 Go build: `NEXO_CORE_GO_BUILD=1 bin/build`
`bin/*` 명령은 로컬 도구가 없으면 일부 검증을 skip할 수 있다. skip 출력이 있으면 최종 보고에 명시한다.
## 도메인 매핑
| 경로 패턴 | 도메인 | rules.md |
|----------|--------|----------|
| `services/core/**` | core-service | `agent-ops/rules/project/domain/core-service/rules.md` |
| `packages/messaging_flutter/**` | messaging-flutter | `agent-ops/rules/project/domain/messaging-flutter/rules.md` |
| `apps/client/**` | client-app | `agent-ops/rules/project/domain/client-app/rules.md` |
| `docs/**`, `bin/**`, root docs/config | workspace-ops | `agent-ops/rules/project/domain/workspace-ops/rules.md` |
## 스킬 라우팅
현재 프로젝트 전용 skill은 없다. 반복 작업이 안정적으로 드러나면 `agent-ops/skills/project/<skill-name>/SKILL.md`로 추가한다.

View file

@ -0,0 +1,28 @@
# 현재 로드맵 컨텍스트
## 활성 Phase
- [<스케치 | 계획 | 진행중 | 검토중 | 보류>] <phase-name>
- 경로: `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`
## 활성 Milestone
- [<스케치 | 계획 | 진행중 | 검토중 | 보류>] <milestone-name>
- Phase: `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`
- 경로: `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`
## 선택 규칙
- 이 문서는 활성 Phase와 활성 Milestone 후보 목록이며, 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
- 활성 Phase는 `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
- 활성 Milestone은 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
- 활성 항목은 아카이브 경로를 포함하지 않는다.
- `[검토중]` 항목은 사용자 완료 확인 전까지 활성 항목으로 남길 수 있다.
- `[스케치]` 항목은 활성 후보로 남길 수 있지만 구현 계획 생성 대상은 아니며, `[계획]` 승격 조건을 정리하는 대상으로만 다룬다.
- `[완료]` 또는 `[폐기]` 항목은 archive 링크를 남긴 뒤 활성 항목에서 제거한다.
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 Phase와 Milestone을 선택하고 같은 세션에서 1회 읽는다.
- 활성 Phase 또는 Milestone 둘 이상에 걸치면 필요한 문서를 모두 읽고 작업 범위를 좁힌다.
- 활성 범위 밖의 작업이면 `agent-ops/roadmap/ROADMAP.md`의 Phase 흐름을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
- 완료된 과거 내용이 필요할 때만 `ROADMAP.md` 또는 `PHASE.md`에 있는 archive 링크를 따라가서 읽는다.
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 구현이나 구현 계획을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다. 관련 결정이 없고 표준선으로 처리 가능하면 잠금을 유지한 채 진행할 수 있으며, Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 `구현 잠금` 상태를 `해제`로 둔다.
- 선택된 Milestone 상태가 `[스케치]`이면 `구현 잠금` 상태와 관계없이 구현이나 구현 계획을 시작하지 않고 `[계획]` 승격 필요를 보고한다.

View file

@ -0,0 +1,85 @@
# Milestone: <Milestone 이름>
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`
## 목표
< Milestone이 끝났을 달성되어야 하는 결과를 1~3문장으로 작성>
## 상태
[<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>]
## 승격 조건
<!--
[스케치] Milestone일 때만 필수다.
[스케치]에서는 [계획]으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 체크리스트로 적는다.
[계획] 이상 상태에서는 이 섹션을 생략하거나 아래처럼 `- 없음`으로 둔다.
-->
- 없음
<!-- [스케치] 예시:
- [ ] 구현 가능한 목표와 범위를 확정한다.
- [ ] 사용자만 결정할 제품/우선순위/책임 경계를 정리한다.
- [ ] 기능 단위와 후속 구현 Milestone 후보를 나눈다.
-->
## 구현 잠금
- 상태: <잠금 | 해제>
- 결정 필요: <없음 | 아래 체크리스트>
- [ ] <사용자만 결정할 있는 제품/범위/우선순위/책임 경계 질문>
## 범위
- < Milestone에 포함되는 제품/기술/문서 범위>
## 기능
<!--
Epic은 `### Epic: [epic-id] <이름>` 형식을 사용한다.
epic-id는 공백 없는 짧은 ASCII 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 -_+= 만 사용한다.
Task는 `- [ ] [item-id] 설명` 형식을 사용한다.
item-id는 공백 없는 짧은 ASCII 영문/숫자 segment 1~4개로 작성하고 segment 구분자는 -_+= 만 사용한다.
epic-id와 item-id는 해당 Milestone 안에서만 유일하면 되고, 다른 Milestone에서는 같은 id를 다시 사용할 수 있다.
Task는 기능 또는 산출물 단위다. 검증이 필요한 기능만 같은 Task 안에 `검증: <명령/확인 방법/기대 결과>`를 덧붙인다.
Task 체크리스트는 Epic 바로 아래의 flat list로 유지하고, 구현 세부나 테스트만 따로 떼어낸 하위 체크박스는 만들지 않는다.
별도 `완료 기준` 섹션은 만들지 않는다.
-->
### Epic: [epic-id] <Epic 이름>
< Epic이 묶는 capability 또는 산출물 설명>
- [ ] [item-id] <구현 세부가 아니라 Milestone에서 달성해야 capability 또는 산출물>
<!-- 검증이 필요한 기능 Task 예시:
- [ ] [item-id] <기능 설명>. 검증: <명령/확인 방법/기대 결과>
-->
## 완료 리뷰
- 상태: <없음 | 요청됨 | 승인됨 | 보완 필요 | 보류 | 폐기>
- 요청일: <YYYY-MM-DD | 없음>
- 완료 근거: <모든 기능 Task와 Task 안에 명시된 검증 충족 여부를 1~3줄로 요약>
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: <없음 | 보완/보류/폐기 방향성>
## 범위 제외
- < Milestone에서 의도적으로 하지 않는 >
## 작업 컨텍스트
- 관련 경로: `<path>`
- 표준선(선택): <기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 진행할 기본 기준>
- 선행 작업: <없음 또는 Milestone/태스크 이름>
- 후속 작업: <없음 또는 Milestone/태스크 이름>
- 확인 필요: <!-- TODO: 확인 필요 -->

View file

@ -0,0 +1,23 @@
# Phase: <Phase 이름>
## 상태
[<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>]
## 목표
< Phase가 끝났을 달성되어야 하는 결과와 책임 경계를 1~3문장으로 작성>
## Milestone 흐름
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
- [<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>] <Milestone 이름>
- 경로: `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 또는 `agent-ops/roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`
- 요약: <목표 또는 결과 1문장>
## Phase 경계
- < Phase에서 유지할 책임 경계 또는 범위 제외 기준>

View file

@ -0,0 +1,21 @@
# 로드맵 현지점
- [current.md](agent-ops/roadmap/current.md)
- [로드맵: <roadmap-name>](agent-ops/roadmap/ROADMAP.md)
- [Phase: <phase-name>](agent-ops/roadmap/phase/<phase-slug>/PHASE.md)
- [Milestone: <milestone-name>](agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
- [<상태>] <목표 또는 역할 >
- [Milestone: <milestone-name>](agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
- [<상태>] <목표 또는 역할 >
## 전체 Phase 흐름
- [<상태>] [<Phase 이름>](<phase-path>)
- [<상태>] [<현재 Phase 이름>](<phase-path>) ← 현재
- [<상태>] [<Phase 이름>](<phase-path>)
## 현재 Phase의 Milestone 흐름
- [<상태>] [<Milestone 이름>](<milestone-path>) ← 현재 후보, <역할 태그>
- [<상태>] [<Milestone 이름>](<milestone-path>) ← 현재 후보, <역할 태그>

View file

@ -0,0 +1,41 @@
# 로드맵
## 전체 목표
<프로젝트가 최종적으로 달성하려는 결과를 1~3문장으로 작성>
## Phase 흐름
위에서 아래로 진행된 순서와 예정 흐름을 나타낸다.
완료된 Phase도 로드맵에서 제거하지 않고, archive의 Phase 문서로 연결한다.
검토중 또는 진행중 Phase는 계획 Phase보다 위에 두어, 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Phase는 아직 구현 가능한 계획이 아니므로 계획 Phase보다 아래에 둔다.
- [<스케치 | 계획 | 진행중 | 검토중 | 완료 | 보류 | 폐기>] <Phase 이름>
- 경로: `agent-ops/roadmap/phase/<phase-slug>/PHASE.md` 또는 `agent-ops/roadmap/archive/phase/<phase-slug>/PHASE.md`
- 요약: < Phase의 목표와 역할 1문장>
## 로딩 정책
- 일반 작업에서는 `agent-ops/roadmap/ROADMAP.md`를 매번 읽지 않는다.
- 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-ops/roadmap/current.md`를 먼저 읽는다.
- `current.md`는 현재 작업 위치가 아니라 활성 Phase와 활성 Milestone 후보 목록이다.
- `current.md`에는 개인별 현재 작업 위치나 완료 상태를 기록하지 않는다.
- `current.md`의 활성 Phase는 `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`를 가리킨다.
- `current.md`의 활성 Milestone은 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`를 가리킨다.
- `current.md``agent-ops/roadmap/archive/**` 경로를 활성 항목으로 포함하지 않는다.
- 요청 내용, 현재 브랜치, 변경 파일, 관련 코드 경로를 보고 가장 관련 있는 활성 Phase와 Milestone 문서를 같은 세션에서 1회 읽는다.
- 활성 Phase 또는 Milestone 밖의 작업이면 이 문서의 Phase 흐름을 확인하고 사용자에게 진행 또는 전환 여부를 확인한다.
- 이 문서는 로드맵 생성/갱신, Phase 전환, Phase 추가/수정, 전체 구조 변경 요청이 있을 때만 읽는다.
- 상세 작업은 각 Milestone 문서의 `기능`으로 관리한다. 검증이 필요한 기능만 같은 Task 안에 `검증:`으로 통합한다.
- `[스케치]` Phase/Milestone은 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태이며 구현 계획 생성 대상이 아니다.
- `[스케치]` 항목은 `승격 조건`을 정리해 `[계획]`으로 전환한 뒤 구현 계획을 만든다.
- 모든 기능 Task와 Task 안에 명시된 검증이 충족된 Milestone은 먼저 `[검토중]`으로 두고, 사용자 완료 확인과 archive 승인을 받은 뒤 `[완료]`로 전환한다.
- 완료된 Phase는 `agent-ops/roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
- 진행중 Phase 안에서 완료된 Milestone은 활성 Phase 문서에 짧은 링크를 남기고, 상세 문서는 `agent-ops/roadmap/archive/phase/<phase-slug>/milestones/`로 이동한다.
- archive `PHASE.md`는 Phase 자체가 완료 또는 폐기될 때만 만들며, 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
- `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않는다. 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라가서 읽는다.
- 아카이브된 Phase/Milestone 문서는 최신 템플릿이나 스킬 규약에 맞춰 재포맷하지 않는다.
- 선택된 Milestone의 `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 코드 구현, `agent-task` 구현 계획 생성, 세부 API/파일 구조 확정을 시작하기 전에 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인한다.
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조/도메인 rule/플랫폼 관례로 정할 수 있는 작업은 표준선으로 기록하고 진행할 수 있다.
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `구현 잠금` 상태를 `해제`로 둔다.

View file

@ -0,0 +1,56 @@
---
name: <skill-name>
version: 1.0.0
description: < skill이 하는 일을 줄로 설명. 트리거 키워드 포함 권장>
---
# <skill-name>
## 목적
< skill이 해결하는 문제를 1~2문장으로 설명>
## 언제 호출할지
- < skill을 호출해야 하는 상황 1>
- < skill을 호출해야 하는 상황 2>
- < skill을 호출해야 하는 상황 3>
## 입력
- `<param-name>`: <설명> (필수)
- `<param-name>`: <설명> (선택)
## 먼저 확인할 것
- [ ] <실행 반드시 확인해야 조건 1>
- [ ] <실행 반드시 확인해야 조건 2>
## 실행 절차
1. **<단계명>**
- <세부 행동>
- <세부 행동>
2. **<단계명>**
- <세부 행동>
3. **결과 보고**
- <출력할 내용>
## 실행 결과 검증
- [ ] <실행 확인해야 성공 조건 1>
- [ ] <실행 확인해야 성공 조건 2>
- 검증 실패 시: <실패 취할 행동 롤백, 사용자 알림, 재시도 >
## 출력 형식
```
<출력 예시>
```
## 금지 사항
- <절대 하면 되는 >
- <절대 하면 되는 >

View file

@ -0,0 +1,74 @@
---
name: analyze-roadmap-position
version: 1.11.0
description: "여러 레포를 전환할 때 코드/git 분석 없이 전체 ROADMAP > Phase > Milestone > current 현지점을 링크 달린 breadcrumb와 흐름 목록으로 빠르게 보여주는 읽기 전용 스킬"
---
# 로드맵 현지점
## 목적
여러 레포를 병렬 운용하다가 돌아왔을 때, 현재 작업이 전체 로드맵의 어느 Phase와 Milestone에 있는지 빠르게 보여준다.
기본 출력은 `로드맵 > Phase > Milestone` breadcrumb와 전체 Phase 흐름, 현재 Phase의 Milestone 흐름이다.
코드 진행도 감사, git diff 분석, 테스트 근거 확인, 남은 작업 정밀 판정은 기본 책임이 아니다.
## 언제 호출할지
- 사용자가 "지금 작업이 뭐지?", "현재 작업이 뭐야?", "어디까지 했지?"라고 물을 때
- 사용자가 레포 전환 직후 로드맵상 현재 좌표를 빠르게 알고 싶어 할 때
- "로드맵상 현 위치", "현재 마일스톤 위치", "current 기준 breadcrumb"를 요청할 때
- 구현 시작 전 전체 Roadmap > Phase > Milestone 관계만 확인하면 될 때
## 먼저 확인할 것
- [ ] `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽어 최신 답변 템플릿 확인
- [ ] `agent-ops/roadmap/` 디렉터리 존재 여부 확인
- [ ] `agent-ops/roadmap/current.md` 존재 여부 확인
- [ ] 로드맵이 있으면 `ROADMAP.md``Phase 흐름`을 확인
- [ ] `current.md`의 활성 Phase와 활성 Milestone 이름, 상태, 경로 확인
- [ ] 활성 Phase 문서의 `Milestone 흐름` 확인
- [ ] 활성 Milestone 문서의 제목, `목표`, `상태`만 확인
## 실행 절차
1. `agent-ops/roadmap/` 존재 여부를 확인한다.
- 없으면 로드맵 없음으로 짧게 보고하고 멈춘다.
2. `agent-ops/skills/common/_templates/roadmap-position-report-template.md`를 읽는다.
3. `agent-ops/roadmap/current.md`를 확인한다.
- 없으면 current 없음으로 보고하고, `ROADMAP.md`가 있으면 `Phase 흐름`만 보여준다.
4. `ROADMAP.md``Phase 흐름`을 읽어 전체 Phase 목록을 만든다.
- 각 Phase는 상태, 이름, 링크만 남긴다.
- current의 활성 Phase와 일치하는 항목에 `← 현재` 표시를 붙인다.
- 완료된 Phase가 archive 경로를 가리켜도 링크만 표시하고 archive 문서는 읽지 않는다.
5. current의 활성 Phase 경로를 열고 `Milestone 흐름`을 읽는다.
- 각 Milestone은 상태, 이름, 링크만 남긴다.
- current의 활성 Milestone과 일치하는 항목에 `← 현재 후보` 표시를 붙인다.
6. current의 활성 Milestone 문서를 열고 제목, `목표`, `상태`만 읽는다.
- `기능`, `완료 리뷰`, `범위 제외`, `작업 컨텍스트`는 사용자가 명시적으로 요청한 경우에만 읽는다.
7. 결과를 템플릿 형식 그대로 출력한다.
## 실행 결과 검증
- [ ] `roadmap-position-report-template.md`의 출력 구조를 유지했는가
- [ ] `current.md`, `ROADMAP.md`, 활성 `PHASE.md`, 활성 Milestone의 제목/목표/상태만 기본으로 읽었는가
- [ ] 완료 또는 archive Phase/Milestone은 링크만 표시하고 archive 문서를 읽지 않았는가
- [ ] current가 여러 Milestone을 가리키면 모두 `현재 후보`로 표시했는가
- [ ] 코드 파일, 테스트 파일, `git status`, `git diff`를 기본 동작에서 읽지 않았는가
- [ ] 로드맵 파일을 수정하지 않았는가
## 출력 형식
- 템플릿 경로: `agent-ops/skills/common/_templates/roadmap-position-report-template.md`
- 템플릿을 그대로 복사해 placeholder를 채운다.
- 섹션 제목과 필드명을 임의로 번역, 축약, 삭제하지 않는다.
- current가 여러 Milestone을 가리키면 breadcrumb와 Milestone 흐름에 모두 표시한다.
- 현재 후보의 역할 태그는 `선행 스케치`, `다음 구현 계획`, `검토 후보`, `보류 후보`처럼 짧게 쓴다.
- 로드맵이 없는 프로젝트에서는 로드맵 없음으로 짧게 보고하고 템플릿을 억지로 채우지 않는다.
## 금지 사항
- 기본 동작에서 코드 파일, 테스트 파일, `git status`, `git diff`를 읽지 않는다.
- 기본 동작에서 Milestone의 `기능` 체크리스트를 감사하지 않는다.
- 완료 여부, 남은 작업, 코드와 문서의 동기화 상태를 evidence 기반으로 판정하지 않는다.
- 사용자가 명시하지 않은 상태에서 `ROADMAP.md`, `current.md`, Phase, Milestone 문서를 수정하지 않는다.
- 사용자가 과거 기록 확인을 명시하지 않으면 `agent-ops/roadmap/archive/**`를 읽지 않는다.

View file

@ -0,0 +1,387 @@
---
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 writes follow-up PLAN/CODE_REVIEW files unless the user-review gate requires USER_REVIEW.md. Never stop after verdict append without writing the required next-state artifact.
---
# Code Review
## Purpose
Review the implementation phase of the plan-code-review loop:
```text
plan skill -> implementation -> code-review skill
^ |
+----- issues found: new routed plan/review files
```
## 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/`; if the task group is `m-<milestone-slug>`, report completion metadata for the runtime event. `WARN` or `FAIL` normally writes the next active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md`; if the user-review gate triggers, write `USER_REVIEW.md` instead.
- Do not ask for confirmation before WARN/FAIL follow-up files unless the user-review gate triggers. If details are uncertain but the gate does not trigger, 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.
## User Review Gate
`USER_REVIEW.md` is a loop stop state for cases where automatic follow-up is likely to waste cycles or needs a human decision.
- Compute `review-number` as `count(agent-task/{task_name}/code_review_*.log) + 1` before archiving the active review.
- If `review-number >= 5` and the verdict is `WARN` or `FAIL`, stop the automatic loop and write `USER_REVIEW.md`.
- If `review-number == 1`, the verdict is `FAIL`, and the blocking issue is a test environment problem rather than a repo-fixable implementation issue, stop the automatic loop and write `USER_REVIEW.md`.
- Treat a first-review failure as a test environment problem only with evidence: missing SDK/tool/runtime, unavailable external service, absent secret/credential, unsupported OS/device/interactive environment, or another prerequisite outside the repository. Record the exact command and stdout/stderr. Before claiming a tool is missing, require `command -v <tool>` or the project-equivalent check.
- Do not classify repo-owned setup bugs as environment problems. If a manifest, bootstrap script, test fixture, or documented project entrypoint should provide the dependency, write a normal follow-up plan instead.
- `USER_REVIEW.md` is created from `agent-ops/skills/common/code-review/templates/user-review-template.md`, filled with the archived loop history, current archived plan/review paths, verdict, loop count, blocking evidence, and user decision options.
## Workflow Contract
Active work must live under an active task directory using routed filenames. This is the state protocol shared with the plan skill.
Task path terms:
- `{task_group}` is the top-level work category under `agent-task/`. Normal task groups use a short snake_case name such as `refactoring`.
- Milestone-linked work uses the reserved task group form `m-<milestone-slug>`, where `<milestone-slug>` is the active Milestone filename without `.md`.
- `{subtask_dir}` is used only for split work and follows the indexed directory naming contract, such as `01_core` or `02+01_db`.
- `{subtask_name}` is the short snake_case name after the index or dependency prefix inside `{subtask_dir}`.
- `{task_name}` in headers and templates means the active task path relative to `agent-task/`: either `{task_group}` for a single-plan task or `{task_group}/{subtask_dir}` for a split subtask.
- A single-plan task stores active files directly under `agent-task/{task_group}/`.
- Split work stores active files under `agent-task/{task_group}/{subtask_dir}/`; the parent `agent-task/{task_group}/` is only the grouping folder and must not contain active plan/review files.
Filename rules:
- Plan file: `PLAN-{build_lane}-GNN.md`
- Review file: `CODE_REVIEW-{review_lane}-GNN.md`
- `{lane}` is only `local` or `cloud`; never put model names in filenames.
- `GNN` is a two-digit capability grade from `G01` to `G10`; runtime maps lane+grade to current models externally.
Multi-plan runtime contract:
- Multi-plan work is represented as multiple subtask directories under one shared `{task_group}`. Each subtask directory owns exactly one normal active plan file and one normal active review file.
- Multi-plan subtask directory names encode runtime scheduling metadata:
- `NN_{subtask_name}` has no runtime dependencies.
- `NN+PP[,QQ...]_{subtask_name}` depends on the listed earlier task indices.
- Subtask directory names are the runtime dependency source of truth. Preserve them verbatim; do not normalize, reinterpret, infer extra dependencies from numeric order, or choose execution order by agent judgment.
- If the user/runtime names a task group, task path, or subtask directory that identifies exactly one active review file, review that directory even when other active review files exist.
Milestone task group contract:
- `agent-task/m-<milestone-slug>/` is reserved for Milestone-linked work created by the plan skill.
- Do not treat normal task groups that do not start with `m-` as runtime milestone completion targets.
- For a selected task path, parse only the first path segment as `{task_group}`. If it matches `^m-[a-z0-9][a-z0-9-]*$`, strip `m-` to get `<milestone-slug>`.
- Do not read or modify `agent-ops/roadmap/**` for milestone routing during code-review finalization.
- Do not call `update-roadmap` from this skill. The runtime consumes the PASS completion event, checks current state, resolves the active Milestone, and calls `update-roadmap` if needed.
- For `m-<milestone-slug>` PASS tasks, report the original active task path, final archive path, complete log path, task group, and milestone slug so the runtime has deterministic event inputs.
Review routing rules:
- `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 |
| `USER_REVIEW.md` + `*.log` files | Automatic loop stopped; user decision is required before creating another plan |
| `agent-task/archive/YYYY/MM/{task_name}/complete.log` + `*.log` files | Archived completed task path (PASS); not active |
| Only `*.log` files (no `complete.log`) | Task terminated mid-loop or abandoned |
The implementing agent never archives or deletes active files; archiving is this skill's responsibility.
## Step 1 - Find Active Task
Find active review files with both globs, excluding `agent-task/archive/**`:
- `agent-task/*/CODE_REVIEW-*-G??.md`
- `agent-task/*/*/CODE_REVIEW-*-G??.md`
Also note active user-review stops, excluding `agent-task/archive/**`:
- `agent-task/*/USER_REVIEW.md`
- `agent-task/*/*/USER_REVIEW.md`
| Result | Action |
|--------|--------|
| Exactly one | Review that task; exactly one `PLAN-*-G??.md` is expected beside it |
| None | If one or more `USER_REVIEW.md` files exist, report that user decision is required and list the paths. Otherwise stop and report that no active review exists. |
| 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. |
If a selected task directory contains both `USER_REVIEW.md` and active `PLAN-*-G??.md` or `CODE_REVIEW-*-G??.md`, report an inconsistent loop state instead of overwriting either state.
## Step 2 - Load Context
Count `agent-task/{task_name}/code_review_*.log` in the selected active task directory:
- `0`: first review. Read the active review file, active plan file, every planned source file, related tests, and files importing/imported by changed files up to 2 levels deep.
- `>=1`: follow-up review. Start with `git diff`, `git diff --cached`, and `git log --oneline -5`, then expand to related callers, implementers, tests, and any planned files missing from the diff.
The diff is the starting point, not the boundary. Follow behavior and API connections far enough to judge correctness.
## Step 3 - Pre-Review Checklist
Before writing the verdict:
- Compare actual source files against every planned checklist item.
- Compare the plan `구현 체크리스트` and review stub `구현 체크리스트`; item text/order must match.
- If a checklist item contains integrated verification for a feature, treat that feature item as incomplete until both implementation evidence and the matching verification output are present. Do not accept a separate unchecked completion-criteria item as a substitute.
- Confirm the implementation marked the matching checklist items in the active review file, including the final mandatory `CODE_REVIEW-*-G??.md` completion item.
- 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 follow-up, or USER_REVIEW line.
Do not check archive/next-state items in `코드리뷰 전용 체크리스트` during Step 4. Complete the applicable dedicated checklist items in the archived `code_review_*.log` during Step 7, after archive, next-state writes, and PASS task-directory moves are done.
Severity semantics:
| Verdict | Meaning | Follow-up plan |
|---------|---------|----------------|
| `PASS` | No Required/Suggested issues. Nit-only findings may still PASS. | No |
| `WARN` | One or more Suggested issues, zero Required. | Yes, unless the user-review gate triggers |
| `FAIL` | One or more Required issues. | Yes, unless the user-review gate triggers |
Issue severity:
- `Required`: correctness, API contract, missing required test, missing verification that was integrated into a feature item, 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 plan/review or `USER_REVIEW.md`.
## 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`, apply the user-review gate before writing follow-up files.
If the user-review gate triggers:
- Write `agent-task/{task_name}/USER_REVIEW.md` from `agent-ops/skills/common/code-review/templates/user-review-template.md`.
- Fill every placeholder. Use `loop-limit` or `environment-blocked` as the reason type.
- Include all available archived loop history in chronological order, the current archived plan/review log paths, the final verdict, review number, issue summary, blocking evidence, and the exact user decision needed.
- Do not write a new active `PLAN-{build_lane}-GNN.md` or `CODE_REVIEW-{review_lane}-GNN.md`.
- Do not write `complete.log`.
- If the task group is `m-<milestone-slug>`, report that the milestone task is blocked on user review; do not emit PASS completion metadata and do not call `update-roadmap`.
If the user-review gate does not trigger, write new routed plan/review files using the plan skill format:
- New plan number is the count of `plan_*.log` after archive.
- Header tag is `REVIEW_<PARENT_TAG>`.
- If the selected task group is `m-<milestone-slug>`, write the follow-up plan/review under the same `m-<milestone-slug>` task group.
- Base the follow-up scope directly on the archived review findings. Keep it narrow and actionable.
- Choose lane/grade again; preserve the prior route 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이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [{TAG}-1] {item description} | [ ] |
| [{TAG}-2] {item description} | [ ] |
## 구현 체크리스트
{copy the follow-up plan's 구현 체크리스트 items exactly, preserving order and checkbox text}
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [ ] active `CODE_REVIEW-*-G??.md``code_review_{review_lane}_GNN_N.log`로 아카이브한다.
- [ ] active `PLAN-*-G??.md``plan_{build_lane}_GNN_M.log`로 아카이브한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/``agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md``CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 리뷰어를 위한 체크포인트
{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.
- If verdict is `PASS` and `{task_group}` matches `m-<milestone-slug>`, do not resolve the roadmap target and do not call `update-roadmap`. Report completion event metadata after the task archive move: `origin-task=agent-task/{task_name}` from the original active task path, `task-group={task_group}`, `milestone-slug=<milestone-slug>`, final archive path, `complete.log` path, and archived plan/review log paths.
- The runtime consumes that completion event, checks current state, resolves `agent-ops/roadmap/phase/*/milestones/<milestone-slug>.md`, and calls `update-roadmap` if needed.
- `WARN` and `FAIL` do not update the roadmap Milestone; the follow-up plan remains under the same `m-<milestone-slug>` task group when the original task was Milestone-linked.
- `USER_REVIEW` does not update the roadmap Milestone and does not produce PASS completion metadata. Keep the active task directory in place with `USER_REVIEW.md` and archived plan/review logs until the user decides how to resume, replan, defer, or abandon the task.
- 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, follow-up plan/review write, or `USER_REVIEW.md` write first.
- Do not recreate an active review file just to update this checklist; update the archived `code_review_*.log`.
- Only report after the archived review log has the verdict, applicable checked review-only checklist, required next-state files, for `PASS` the final task archive move, for `m-*` PASS tasks the completion event metadata, and for `USER_REVIEW` the filled `USER_REVIEW.md`.
Report Required/Suggested counts, archive names, the final task archive path for `PASS`, the new plan path for normal `WARN`/`FAIL`, the `USER_REVIEW.md` path for user review stops, and any `m-*` runtime completion event metadata.
## Review Dimensions
| Dimension | Check |
|-----------|-------|
| Correctness | Logic, edge cases, concurrency, errors |
| Completeness | All planned checklist items done, including integrated implementation+verification feature items and 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 milestone task group: `m-<milestone-slug>` completion event metadata was reported for runtime; roadmap was not modified by code-review.
- PASS split: empty active parent `agent-task/{task_group}/` removed after the subtask move; non-empty parent left in place.
- WARN/FAIL without user-review gate: new active `PLAN-{build_lane}-GNN.md` and `CODE_REVIEW-{review_lane}-GNN.md` created with matching headers and matching `구현 체크리스트`; no `complete.log`.
- USER_REVIEW: `USER_REVIEW.md` exists from template, no active `PLAN-*.md` or `CODE_REVIEW-*.md` remains, and no `complete.log` was written.
- The applicable review-agent-only finalization checklist was completed before reporting.

View file

@ -0,0 +1,4 @@
interface:
display_name: "Code Review"
short_description: "Review and route task loops"
default_prompt: "Use $code-review to review the active repository task, archive active files, and create complete.log, follow-up plan/review files, or USER_REVIEW.md."

View file

@ -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
- 없음
## 후속 작업
- 없음

View file

@ -0,0 +1,47 @@
# User Review Required - {task_name}
## 요청 일시
{YYYY-MM-DD or ISO-8601}
## 상태
USER_REVIEW
## 사유
- 유형: {loop-limit or environment-blocked}
- 현재 리뷰 회차: {review-number}
- 최종 판정: {WARN or FAIL}
- 요약: {why automatic follow-up stopped}
## 루프 이력
| Plan | Review | Verdict | 메모 |
|------|--------|---------|------|
| `{plan-log-0}` | `{code-review-log-0}` | {PASS/WARN/FAIL/unknown} | {main issue or blocking reason} |
| `{current-archived-plan-log}` | `{current-archived-review-log}` | {WARN/FAIL} | {main issue or blocking reason} |
## 차단 근거
- 문제: {review finding summary}
- 현재 archive plan: `{current-archived-plan-log}`
- 현재 archive review: `{current-archived-review-log}`
- 검증 명령: `{command or 없음}`
- 실제 출력: {stdout/stderr excerpt or saved output path}
- 환경 판단 근거: {why this is outside repo-fixable scope, or 없음}
## 사용자 결정 필요
- [ ] 자동 follow-up plan/review를 계속 진행한다.
- [ ] 계획을 재작성한다.
- [ ] 테스트 환경, secret, 외부 서비스, SDK, 장비 조건을 준비한 뒤 재시도한다.
- [ ] 작업 범위를 줄이거나 보류/폐기한다.
## 재개 조건
- {what must be true before the next plan/review loop should start}
## 다음 실행 힌트
- {suggested command, task path, or user decision needed to resume}

View 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` 옵션을 사용하지 않는다

View 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 파일 생성만 담당한다

View 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에 길게 복사하지 않는다.

View file

@ -0,0 +1,174 @@
---
name: create-roadmap
version: 1.14.0
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase scaffold, Phase 하위 Milestone 문서, current.md 활성 Phase/Milestone 창, archive Phase scaffold를 처음 생성하는 공통 스킬
---
# 로드맵 생성
## 목적
`agent-ops/roadmap/` 하위에 `Roadmap -> Phase -> Milestone` 기반 한국어 로드맵 구조를 처음 생성한다.
전체 로드맵은 전체 방향과 Phase index만 담당하고, 일반 작업에서는 `current.md`의 활성 Phase/Milestone 링크와 관련 문서만 읽도록 만든다.
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서다.
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.
## 언제 호출할지
- 프로젝트에 파일 기반 로드맵을 처음 만들 때
- 사용자가 "로드맵 만들어줘", "마일스톤 설계해줘", "goal/phase 구조 잡아줘"라고 요청할 때
- 기존 README나 메모에 흩어진 계획을 `agent-ops/roadmap/` 구조로 분리할 때
## 입력
- `overall-goal`: 프로젝트 전체 목표 한 줄 또는 짧은 문단 (선택, 없으면 README와 현재 구조에서 추론)
- `phase-hints`: 예상 Phase 목록 또는 단계 힌트 (선택)
- `milestone-hints`: 예상 Milestone 목록 또는 기능 힌트 (선택)
- `active-phases`: 현재 열어둘 Phase 목록 (선택, 없으면 현재 구현 상태와 요청에서 추론)
- `active-milestones`: 현재 열어둘 Milestone 목록 (선택, 없으면 현재 구현 상태와 요청에서 추론)
## 생성 구조
```text
agent-ops/
roadmap/
ROADMAP.md
current.md
phase/
<phase-slug>/
PHASE.md
milestones/
<milestone-slug>.md
archive/
phase/
<phase-slug>/
PHASE.md
milestones/
<milestone-slug>.md
```
| 파일 | 역할 |
|------|------|
| `agent-ops/roadmap/ROADMAP.md` | 전체 목표와 Phase 흐름만 담는 최상위 지도. 로드맵 생성/갱신/Phase 전환 때만 읽는다 |
| `agent-ops/roadmap/current.md` | 활성 Phase와 활성 Milestone 후보, 선택 규칙을 담는 얇은 포인터 |
| `agent-ops/roadmap/phase/<phase-slug>/PHASE.md` | Phase 목표, 상태, Milestone 흐름, Phase 경계를 담는 문서 |
| `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` | 일반 작업 시 읽는 Milestone 단위 목표, 스케치 승격 조건, 구현 잠금, 범위, 기능 Epic/Task 체크리스트, 범위 제외 항목 |
| `agent-ops/roadmap/archive/phase/<phase-slug>/...` | 완료 또는 폐기되어 현재 후보에서 제외한 과거 Phase/Milestone. 일반 작업에서는 읽지 않는다 |
## 템플릿
- `ROADMAP.md``agent-ops/skills/common/_templates/roadmap-template.md` 형식을 따른다.
- `current.md``agent-ops/skills/common/_templates/roadmap-current-template.md` 형식을 따른다.
- `PHASE.md``agent-ops/skills/common/_templates/roadmap-phase-template.md` 형식을 따른다.
- Milestone 문서는 `agent-ops/skills/common/_templates/roadmap-milestone-template.md` 형식을 따른다.
- `ROADMAP.md`에는 Milestone 상세 체크리스트를 넣지 않는다.
- `current.md`는 활성 Phase/Milestone 후보만 담고, 개인별 현재 작업 위치나 완료 상태를 적지 않는다.
- archive 경로는 `current.md`의 활성 항목에 넣지 않는다.
## 작성 규칙
- 기본 작성 언어는 한국어다.
- 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 구현 계획 생성 대상이 아니다.
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 정리되어 구현 계획을 만들 수 있는 상태다.
- Phase와 Milestone 이름, 파일명에는 `1`, `2`, `M01`, `P1` 같은 순번을 붙이지 않는다.
- 진행 순서는 `ROADMAP.md`와 각 `PHASE.md`의 위에서 아래 순서로 표현한다.
- Phase 파일명은 `agent-ops/roadmap/phase/<phase-slug>/PHASE.md`로 만든다.
- Milestone 파일명은 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`로 만든다.
- `<phase-slug>``<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용하고, 공백/언더스코어/순번 prefix를 넣지 않는다.
- 중간에 Phase나 Milestone을 끼워 넣을 수 있도록 기존 항목의 이름과 파일명을 불필요하게 바꾸지 않는다.
## Milestone 작성 규칙
- Milestone 기본 섹션은 `위치`, `목표`, `상태`, `구현 잠금`, `범위`, `기능`, `완료 리뷰`, `범위 제외`, `작업 컨텍스트`다.
- `승격 조건``[스케치]` Milestone에서 필수다. `[계획]` 이상 상태에서는 섹션을 생략하거나 `- 없음`으로 둘 수 있다.
- `[스케치]` Milestone은 `승격 조건`을 체크리스트로 작성하고, `[계획]`으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 적는다.
- 새 Milestone은 사용자만 결정할 수 있는 제품 방향, 범위, 우선순위, 책임 경계가 남아 있으면 `구현 잠금``잠금`으로 둔다.
- 새 `[스케치]` Milestone은 `구현 잠금``잠금`으로 둔다.
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
- `구현 잠금`에는 상태와 `결정 필요` 체크리스트만 적는다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적는다.
- `기능`은 Epic heading과 Task 체크리스트로 작성한다.
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
- Task는 `- [ ] [item-id] 설명` 형식으로 작성한다.
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
- 검증이 필요한 Task에만 같은 항목 안에 `검증: <명령/확인 방법/기대 결과>`를 붙인다. 검증이 필요 없는 기능에는 억지 검증을 붙이지 않는다.
- `완료 리뷰`는 새 Milestone에서는 `상태: 없음`, `요청일: 없음`으로 두고, 모든 기능 Task와 Task 안에 명시된 검증이 충족된 뒤 사용자 최종 확인을 요청할 때 갱신한다.
- `범위`, `범위 제외`, `작업 컨텍스트`는 설명 목록으로 작성하고, 실행해야 할 작업을 이 섹션에 숨기지 않는다.
## 먼저 확인할 것
- [ ] `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`로 현재 프로젝트의 주요 구조를 가볍게 확인
- [ ] `roadmap-template.md`, `roadmap-current-template.md`, `roadmap-phase-template.md`, `roadmap-milestone-template.md`를 읽어 최신 형식 확인
- [ ] `agent-ops/rules/common/rules.md`가 로드맵 디렉터리 존재 시 `agent-ops/rules/common/rules-roadmap.md`를 읽도록 라우팅하는지 확인
## 실행 절차
1. **기존 로드맵 확인**
- `agent-ops/roadmap/` 하위 기존 파일 존재 여부를 확인한다.
- 기존 로드맵이 있으면 새로 만들지 않고 `update-roadmap`을 사용하도록 안내한다.
2. **프로젝트 방향 분석**
- README와 프로젝트 규칙에서 대상 사용자, 해결하려는 문제, 현재 구현 상태를 파악한다.
- 전체 코드를 정독하지 않는다. 로드맵 설계에 필요한 문서와 상위 구조만 확인한다.
- 불확실한 제품 방향은 단정하지 않고 "가정" 또는 `<!-- TODO: 확인 필요 -->`로 남긴다.
3. **목표 / Phase / Milestone 설계**
- 전체 목표는 프로젝트가 궁극적으로 만들려는 결과를 1~3문장으로 작성한다.
- Phase는 큰 진화 단위로 나누고, 각 Phase에 목표와 상태를 둔다.
- Milestone은 Phase 안에서 완료 판단이 가능한 단위로 나눈다.
- Milestone 내부에서 여러 기능 묶음이 필요하면 Epic으로 선언하고, Epic 아래 flat Task 체크리스트를 둔다.
4. **파일 생성**
- `ROADMAP.md`, `current.md`, 각 Phase의 `PHASE.md`, 각 Milestone 문서를 템플릿 순서대로 생성한다.
- 활성 Phase와 활성 Milestone은 `current.md`에 모두 기록한다.
- `ROADMAP.md`의 Phase 흐름에는 완료/검토중/진행중/계획/스케치 Phase 모두를 위에서 아래 순서로 두고, 계획 Phase는 진행중 Phase보다 아래에, 스케치 Phase는 계획 Phase보다 아래에 둔다.
- 완료된 Phase가 초기 구조에 포함되어야 하는 경우 `archive/phase/<phase-slug>/PHASE.md`로 만들고 `ROADMAP.md`에서 archive 경로를 가리킨다.
- 완료된 Milestone이 진행중 Phase에 포함되어야 하는 경우 `archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 만들고 해당 활성 `PHASE.md`에서 archive 경로를 가리킨다.
- archive `PHASE.md`는 Phase 자체가 완료/폐기된 경우에만 만든다. 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 둘 수 있다.
5. **검증**
- 생성한 링크가 실제 파일을 가리키는지 확인한다.
- `current.md` 활성 항목에 `agent-ops/roadmap/archive/**` 경로가 없는지 확인한다.
- Epic heading과 Task 체크리스트 id가 형식을 따르는지 확인한다.
- 상태 표기가 `[진행중]`처럼 공백 없는 표준값인지 확인한다.
- `[스케치]` Milestone에 `승격 조건` 섹션이 있고 `구현 잠금``잠금`인지 확인한다.
- Milestone 문서에 `완료 리뷰` 섹션이 있는지 확인한다.
## 출력 형식
```markdown
## 생성 완료
- 로드맵: agent-ops/roadmap/ROADMAP.md
- 현재 컨텍스트: agent-ops/roadmap/current.md
- Phase 문서: <N개>
- Milestone 문서: <N개>
- 활성 Phase: <N개>
- 활성 Milestone: <N개>
- 구현 잠금: <잠금 Milestone N개 | 해제 Milestone N개>
- 공통 로드맵 룰: <확인함 | 설치 필요 | 해당 없음>
## 활성 항목
- Phase: <phase-name>: agent-ops/roadmap/phase/<phase-slug>/PHASE.md
- Milestone: <milestone-name>: agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md
## TODO 항목
- <확인이 필요한 가정 또는 미정 항목> (해당 시)
```
## 금지 사항
- 기존 `agent-ops/roadmap/` 파일을 덮어쓰지 않는다.
- 일반 작업마다 전체 `ROADMAP.md`를 읽도록 규칙을 만들지 않는다.
- `current.md``agent-ops/roadmap/archive/**` 경로를 넣지 않는다.
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 넣지 않는다.
- Epic과 Task를 별도 파일로 분리하지 않는다.
- Milestone 문서에서 `구현 잠금` 섹션을 생략하지 않는다.
- 사용자만 결정할 수 있는 항목이 남아 있는데 새 Milestone을 `해제` 상태로 만들지 않는다.
- 확정되지 않은 제품 방향을 사실처럼 단정하지 않는다.

View file

@ -0,0 +1,101 @@
---
name: create-skill
version: 1.0.0
description: 새로운 SKILL.md 파일을 생성하기 위한 범용 스킬
---
# Create Skill
## 목적
`agent-ops/skills/` 하위에 올바른 형식의 SKILL.md 파일을 생성한다.
기존 skill-template.md 를 기반으로, 요청 목적에 맞는 내용을 채워 넣는다.
생성 후 라우팅 항목을 추가한다.
이 스킬은 프로젝트 내부 `agent-ops` 라우터가 읽는 스킬을 만든다.
`$CODEX_HOME/skills`에 설치되어 Codex가 직접 discover하는 스킬을 만들 때는 시스템 `skill-creator` 규칙을 우선하고, frontmatter는 `name``description`만 사용한다.
### 생성 위치 결정
- `.agent-ops-source` 파일이 **있으면** (공통 관리 레포): `agent-ops/skills/common/<skill-name>/SKILL.md`
- `.agent-ops-source` 파일이 **없으면** (타겟 프로젝트): `agent-ops/skills/project/<skill-name>/SKILL.md`
## 언제 호출할지
- 새로운 반복 작업 패턴이 생겨 skill로 정의해야 할 때
- 기존 skill이 없는 작업 유형을 처음 수행하기 전에
- 사용자가 특정 작업을 skill로 만들어 달라고 요청할 때
## 입력
- `skill-name`: 생성할 skill 이름, kebab-case (필수)
- `purpose`: 이 skill이 해결하는 문제 한 줄 요약 (필수)
- `trigger-cases`: 이 skill을 호출해야 하는 상황 목록 (선택)
## 먼저 확인할 것
- [ ] `agent-ops/skills/common/``agent-ops/skills/project/` 하위에 동일 이름의 디렉터리가 이미 존재하는지 확인
- [ ] `agent-ops/skills/common/router.md``agent-ops/rules/project/rules.md` 에 이미 유사한 라우팅 항목이 있는지 확인
- [ ] `agent-ops/skills/common/_templates/skill-template.md` 를 읽어 최신 템플릿 형식 파악
## 실행 절차
1. **중복 확인**
- `agent-ops/skills/common/<skill-name>/``agent-ops/skills/project/<skill-name>/` 폴더 존재 여부 확인
- 기능이 겹치는 기존 skill이 있으면 사용자에게 알리고 중단한다
2. **목적 분석**
- `purpose``trigger-cases` 를 바탕으로 아래 항목을 도출한다
- 언제 호출할지 (2~4개)
- 필요한 입력 파라미터
- 사전 확인 항목
- 실행 절차 (3~7단계)
- 출력 형식
- 금지 사항
3. **SKILL.md 생성**
- 경로: 생성 위치 결정 규칙에 따라 `common/` 또는 `project/` 하위에 생성
- `skill-template.md` 형식을 따른다
- agent-ops 내부 스킬은 기존 로컬 관례에 맞춰 `version`을 둘 수 있다. Codex 설치형 스킬로 배포할 목적이면 `version`이나 `depends` 같은 비표준 frontmatter를 넣지 않는다.
- 프로젝트 특화 내용보다 범용 절차를 우선한다
- 절차는 구체적이되 지나치게 세부 구현을 기술하지 않는다
4. **라우팅 업데이트**
- `.agent-ops-source` 마커가 **있으면** (공통 관리 레포): `agent-ops/skills/common/router.md`에 라우팅 항목 추가
- `.agent-ops-source` 마커가 **없으면** (타겟 프로젝트): `agent-ops/rules/project/rules.md`의 프로젝트 스킬 라우터 섹션에 라우팅 항목 추가
- 기존 공통 스킬을 수정해 trigger가 달라졌다면 새 skill을 만들지 말고 `agent-ops/skills/common/router.md`의 기존 행을 갱신한다
- 이 skill이 속할 라우팅 축(구조 분석/코드 변경/흐름 추적 등)을 판단한다
- 기존 라우팅 구조를 깨지 않는다
5. **결과 보고**
- 생성한 파일 경로
- 라우팅 항목을 추가한 파일과 내용
- 이 skill이 다루지 않는 범위(필요 시)
## 출력 형식
```
## 생성 완료
- SKILL 경로: agent-ops/skills/{common|project}/<skill-name>/SKILL.md
- 라우팅 추가: <대상 파일><라우팅 ><skill-name>
## 주의사항 (해당 시)
- < skill이 다루지 않는 범위 또는 주의할 >
```
## 실행 결과 검증
- [ ] `agent-ops/skills/{common|project}/<skill-name>/SKILL.md` 파일이 생성되었는가
- [ ] 생성된 파일이 `skill-template.md`의 필수 섹션(목적, 언제 호출할지, 실행 절차, 실행 결과 검증, 출력 형식, 금지 사항)을 포함하는가
- [ ] frontmatter에 name, description이 올바르게 기재되었는가
- [ ] agent-ops 내부 스킬이면 version 등 로컬 관례를 따르고, Codex 설치형 스킬이면 시스템 `skill-creator` frontmatter 규칙을 따르는가
- [ ] 라우팅 대상 파일에 해당 스킬의 라우팅 항목이 추가되었는가
- 검증 실패 시: 누락된 섹션 또는 라우팅 항목을 사용자에게 알리고 해당 부분만 보완한다
## 금지 사항
- 이미 존재하는 skill 을 덮어쓰지 않는다
- 프로젝트 특화 경로(예: `app/screens/`)를 skill 본문에 하드코딩하지 않는다
- skill 생성과 무관한 코드 파일을 수정하지 않는다
- 라우팅 대상 파일의 기존 항목을 삭제하거나 재정렬하지 않는다
- 하나의 skill 에 여러 독립적인 책임을 묶지 않는다

View file

@ -0,0 +1,254 @@
---
name: init-agent-ops
version: 1.1.4
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-Ops 관리 block에 `agent-task/archive/**`, `agent-ops/roadmap/archive/**` 추가 |
| `.claude/settings.json`, `opencode.json` | `agent-task/archive/**` 읽기/검색 제외 설정을 생성 또는 병합한다. `agent-ops/roadmap/archive/**`는 필요 시 링크로 읽을 수 있어야 하므로 hard read/glob deny에서 제거한다 |
에이전트별 파일명:
실제 생성/동기화 대상 목록은 `agent-ops/bin/entry-files.sh``AGENT_OPS_ENTRY_FILES`를 단일 기준으로 사용한다.
| 에이전트 | 파일명 |
|---------|--------|
| Gemini | `GEMINI.md` |
| Claude | `CLAUDE.md` |
| Kilo Code / OpenCode | `AGENTS.md` |
| Cursor | `.cursorrules` |
| Cline | `.clinerules` |
## 에이전트 진입 파일 원칙
진입 파일은 `rules/common/rules.md` 내용 그대로를 에이전트별 파일명으로 복사한다.
별도 내용을 추가하거나 수정하지 않는다.
## Rule 구조 원칙
### rules/common/rules.md
- 공통 관리 레포에서 제공. 프로젝트에서 직접 수정하지 않는다.
- 실제 사용은 진입점 파일들에서 사용된다.
포함 항목:
- 기본 원칙
- 공통 스킬 라우팅 (router.md 참조)
- project/rules.md 로드 지시
### rules/project/rules.md
init-agent-ops가 프로젝트를 분석하여 생성한다.
포함 항목:
- 응답 언어
- 프로젝트 개요 / 주요 구조
- 기술 스택
- 프로젝트 특화 컨벤션
- 도메인 매핑 테이블 (경로 패턴 → domain rules.md)
- 프로젝트 스킬 라우팅 (해당 시)
common/rules.md와 내용이 중복되지 않도록 한다.
#### 도메인 매핑 테이블 형식
```markdown
## 도메인 매핑
| 경로 패턴 | 도메인 | rules.md |
|----------|--------|----------|
| `src/order/**` | order | `agent-ops/rules/project/domain/order/rules.md` |
| `src/payment/**` | payment | `agent-ops/rules/project/domain/payment/rules.md` |
| `src/common/**` | common | `agent-ops/rules/project/domain/common/rules.md` |
```
#### 프로젝트 스킬 라우팅 형식
```markdown
## 스킬 라우팅
| 요청 키워드 | SKILL.md |
|------------|----------|
| 테스트 실행해줘 | `agent-ops/skills/project/run-test/SKILL.md` |
```
### domain rule
각 도메인 rules.md에는 아래만 둔다.
- frontmatter metadata
- `domain`
- `last_rule_review_commit`: 생성 직전 `git rev-parse HEAD`
- `last_rule_updated_at`: 생성일 `YYYY-MM-DD`
- 목적 / 책임
- 포함 경로
- 제외 경로
- 주요 구성 요소
- 유지할 패턴
- 다른 도메인과의 경계
- 금지 사항
## DDD 기준
- **Core Domain**: 핵심 가치와 주요 유즈케이스
- **Supporting Domain**: 핵심 도메인을 지원
- **Generic / Common**: 여러 도메인이 공통으로 사용
도메인은 실제 폴더, 모듈, 패키지, 책임 경계와 연결되어야 한다.
## 실행 (Execution)
지정한 대상 디렉토리에 agent-ops 스캐폴드를 생성한다.
```bash
./agent-ops/bin/init-agent-ops.sh <target_directory>
```
## 실행 절차
1. **상태 판별**
- 프로젝트 구조, 모듈 경계, agent-ops 파일 유무를 분석하여 신규/운영중을 판별한다
2. **에이전트 진입 파일 생성**
- `rules/common/rules.md``agent-ops/bin/entry-files.sh`의 파일 목록으로 프로젝트 루트에 복사한다
3. **AI ignore / permission 기본 설정**
- `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에는 사용자 항목을 건드리지 않고 Agent-Ops 관리 block만 추가하거나 교체한다
- Agent-Ops 관리 block에는 `agent-task/archive/**``agent-ops/roadmap/archive/**`를 넣는다
- `.claude/settings.json`, `opencode.json`이 없으면 `agent-task/archive/**` 읽기/검색 제외 설정을 생성하고, 있으면 가능한 경우 기존 설정을 보존하며 필요한 제외 설정만 병합한다
- `agent-ops/roadmap/archive/**`는 일반 작업에서 읽지 않도록 AI ignore와 로드맵 규칙으로 제한하되, `.claude/settings.json`이나 `opencode.json`의 hard read/glob deny에는 두지 않는다
- 기존 `.claude/settings.json`이나 `opencode.json``agent-ops/roadmap/archive/**` hard read/glob deny가 있으면 init-agent-ops 표준에 맞게 제거한다
- 대상 루트에 `.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-Ops 관리 block이 있고 그 안에 `agent-task/archive/**``agent-ops/roadmap/archive/**`가 포함되어 있는가
- [ ] `.claude/settings.json`, `opencode.json``agent-task/archive/**` 제외 설정이 있거나, 병합 불가 시 수동 병합 안내를 출력했는가
- [ ] `.claude/settings.json`, `opencode.json``agent-ops/roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
- [ ] 기존 `agent-ops/roadmap/archive/**` hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
- [ ] `.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와 중복되는 내용을 넣지 않는다.

View file

@ -0,0 +1,403 @@
---
name: plan
description: Analyze the current repository and write a detailed PLAN-{build_lane}-GNN.md for implementation work. Also writes the CODE_REVIEW-{review_lane}-GNN.md stub that the implementing agent will fill in after coding. Use for any feature, refactor, bug fix, or follow-up fix that should enter the plan-code-review loop. Milestone-linked work uses a reserved m-prefixed task group so runtime can route PASS completion events to update-roadmap. A separate implementing agent, or the same agent in an implementation pass, reads the plan file and does the coding.
---
# Plan
## Purpose
Create the planning artifacts for the implementation loop:
```text
plan skill -> PLAN-{build_lane}-GNN.md + CODE_REVIEW-{review_lane}-GNN.md stub
implementation -> code changes + filled CODE_REVIEW-{review_lane}-GNN.md
code-review skill -> verdict + archive, complete.log, and PASS task-directory archive move, new follow-up plan/review files, or USER_REVIEW.md
runtime -> for m-prefixed PASS completion events, state check and optional update-roadmap call
```
`code-review` may stop the automatic loop with `USER_REVIEW.md` when repeated non-PASS reviews or first-review test environment blockers require a user decision. Plan creation after `USER_REVIEW.md` requires an explicit user decision.
## Workflow Contract
This skill intentionally uses routed active files under an active task directory as the state protocol. Do not change this directory or filename contract unless the paired code-review skill is updated together.
Task path terms:
- `{task_group}` is the top-level work category under `agent-task/`. Normal task groups use a short snake_case name such as `refactoring`.
- Milestone-linked work uses the reserved task group form `m-<milestone-slug>`, where `<milestone-slug>` is the active Milestone filename without `.md`.
- `{subtask_dir}` is used only for split work and follows the existing indexed directory naming rules below, such as `01_core` or `02+01_db`.
- `{subtask_name}` is the short snake_case name after the index or dependency prefix inside `{subtask_dir}`.
- `{task_name}` in headers and templates means the active task path relative to `agent-task/`: either `{task_group}` for a single-plan task or `{task_group}/{subtask_dir}` for a split subtask.
- A single-plan task stores active files directly under `agent-task/{task_group}/`.
- Split work stores active files under `agent-task/{task_group}/{subtask_dir}/`; the parent `agent-task/{task_group}/` is only the grouping folder and must not contain active plan/review files.
Filename rules:
- Plan file: `PLAN-{build_lane}-GNN.md`
- Review stub: `CODE_REVIEW-{review_lane}-GNN.md`
- `{lane}` is only `local` or `cloud`; never put model names in filenames.
- `GNN` is a two-digit capability grade from `G01` to `G10`; the runtime maps lane+grade to current models externally.
Role boundary rules:
- Implementing agents fill implementation-owned `CODE_REVIEW-*-G??.md` sections, keep active files in place, and report ready for review.
- 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 normal single-plan task uses `agent-task/{task_group}/` with a short snake_case category name, e.g. `agent-task/refactoring/`.
- If the plan is based on a selected active Milestone, use `agent-task/m-<milestone-slug>/` as the task group. Do not include the Phase slug, Epic id, Task id, or a separate task slug in the task group.
- `m-<milestone-slug>` is a reserved top-level task group namespace for Milestone-linked work. Non-roadmap tasks must not use `m-`.
- Runtime completion-event routing for `m-*` reads only the top-level `{task_group}` name. It resolves `<milestone-slug>` by matching exactly one active file at `agent-ops/roadmap/phase/*/milestones/<milestone-slug>.md`; archive paths are not target candidates.
- When split gates require decomposition, create one shared category folder and multiple subtask directories under it. Each subtask directory owns exactly one normal active plan file and one normal active review stub.
- Multi-plan output is a set of independent `PLAN-{build_lane}-GNN.md` + `CODE_REVIEW-{review_lane}-GNN.md` pairs across `agent-task/{task_group}/{subtask_dir}/` folders, not multiple plan files inside one folder.
- Multi-plan subtask directory names must start with a stable two-digit task index. The index must increase across sibling subtask directories for sorting, but it is not a serial execution dependency.
- Use `NN_{subtask_name}` for a task with no runtime dependencies, e.g. `01_core`, `04_docs`, `05_ui`.
- Use `NN+PP[,QQ...]_{subtask_name}` for a task that depends on earlier task indices, e.g. `02+01_db`, `03+01,02_api`, `06+05_integration`.
- Valid independent pattern: `^[0-9]{2}_[a-z0-9_]+$`.
- Valid dependent pattern: `^[0-9]{2}\+[0-9]{2}(,[0-9]{2})*_[a-z0-9_]+$`.
- `NN`, `PP`, and `QQ` are two-digit indices. Every predecessor index after `+` must be lower than `NN` and must refer to a sibling multi-plan subtask directory under the same `{task_group}`.
- The first `_` after the index or dependency list starts `{subtask_name}`. `{subtask_name}` stays short snake_case and may contain additional underscores.
- Runtime scheduling reads only the `{subtask_dir}` name: `_` means `depends_on=[]`; `+` means `depends_on` is the comma-separated index list between `+` and the first `_`.
- Subtask directory names are the source of truth for runtime dependencies. Do not hide extra dependencies only in the plan body, and do not create a bare `NN+{subtask_name}` without predecessor indices.
- 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 |
| `USER_REVIEW.md` + `*.log` files | Automatic loop stopped; user decision is required before creating another plan |
| `agent-task/archive/YYYY/MM/{task_name}/complete.log` + `*.log` files | Archived completed task path (PASS); not active |
| Only `*.log` files (no `complete.log`) | Task terminated mid-loop or abandoned |
## Step 1 - Determine Task
If the user names the task explicitly, use that task group or task path.
Otherwise, find active plan files with both globs, excluding `agent-task/archive/**`:
- `agent-task/*/PLAN-*-G??.md`
- `agent-task/*/*/PLAN-*-G??.md`
Also note active user-review stops, excluding `agent-task/archive/**`:
- `agent-task/*/USER_REVIEW.md`
- `agent-task/*/*/USER_REVIEW.md`
| Result | Action |
|--------|--------|
| Exactly one | Continue that task |
| None | Create a new task only for a feature/refactor/fix/follow-up that belongs in this workflow |
| Multiple | If the user/runtime named a task group, task path, or subtask directory that identifies exactly one active plan, use it. Otherwise list paths and ask which task to use; do not choose by agent judgment. |
The routed plan file is the loop entry point. A missing active plan normally means only that no plan has been started for a new task; do not create task files for casual analysis, status, or review requests unless the user explicitly asks for a plan.
If no active plan exists but one or more `USER_REVIEW.md` files exist, report that user decision is required and list the paths unless the user explicitly asked to resume one of them. If a selected active task directory contains `USER_REVIEW.md`, read it before planning. Do not write a new follow-up plan unless the user explicitly decides to continue, replan, retry after preparing the environment, or change the task scope. When planning resumes from `USER_REVIEW.md`, archive it to `user_review_N.log` in the same task directory before writing the new active plan/review pair, and record the user decision in the new plan `배경` or `분석 결과`.
If a selected task directory contains both `USER_REVIEW.md` and active `PLAN-*-G??.md` or `CODE_REVIEW-*-G??.md`, report an inconsistent loop state and do not overwrite either state until the user decides whether to resume from user review or continue the active plan/review.
로드맵 확인:
- `agent-ops/roadmap/current.md`가 있으면 구현 계획 파일을 만들기 전에 읽고, 사용자 요청, 브랜치, 변경 경로를 기준으로 관련 Phase와 Milestone을 선택한다.
- `current.md``agent-ops/roadmap/archive/**`를 가리키면 해당 문서는 읽지 말고 활성 Phase/Milestone이 아니라고 보고한다.
- 선택한 Phase를 한 번 읽어 Phase 목표, Milestone 흐름, Phase 경계를 확인한다.
- 선택한 Milestone을 한 번 읽어 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. `승격 조건``[스케치]`에서만 필수이며, `[계획]` 이상에서 섹션이 없으면 `없음`으로 본다. `구현 잠금` 섹션이 없거나 상태가 `잠금`이면 현재 요청에 직접 영향을 주는 `결정 필요` 항목만 확인하고, 그 결정 없이는 `PLAN-*-G??.md`, `CODE_REVIEW-*-G??.md`, file/API/package 수준 구현 단계를 확정하지 않는다.
- 선택한 Milestone에 legacy `필수 기능`/`완료 기준`이 분리되어 있으면 plan 작성 전에 roadmap preflight로 정규화한다. 흡수 가능한 기준은 관련 기능 Task 안의 선택적 `검증:` 또는 Task 설명으로 즉시 흡수하고, 어느 기능에도 붙지 않는 기준이 남으면 plan 파일을 만들지 말고 남은 기준과 필요한 사용자 판단을 구체적으로 보고한다.
- 선택한 Phase 또는 Milestone 상태가 `[스케치]`이면 구현 계획 파일을 만들지 않는다. `[스케치]`는 컨셉 상태이므로 `update-roadmap`의 concretize 흐름으로 승격 조건, 결정 필요, 범위, 기능 Task를 정리해 `[계획]`으로 전환해야 한다고 보고한다.
- Phase 또는 Milestone 후보가 여럿이면 요청 문장, 변경 경로 직접성, Milestone 상태, 구현 잠금, 선후 의존성, Phase/Milestone 흐름상 위치를 기준으로 1순위와 2순위를 추천하고 필요한 후보 문서만 읽어 범위를 좁힌다.
- 로드맵 current가 있고 활성 Phase/Milestone 밖 작업이면 `ROADMAP.md`의 Phase 흐름을 확인하고 전환, 신규 Phase/Milestone, 또는 기존 활성 범위 내 배치 필요성을 보고한다.
- 현재 요청과 직접 관련 없는 미정 항목은 잠금 상태로 남겨도 되며, 기존 구조, 도메인 rule, 플랫폼 관례로 정할 수 있는 세부는 표준선/가정으로 계획에 기록하고 진행할 수 있다.
- 사용자가 선택한 Milestone의 작업, 구현, 계획 작성을 명시했고 현재 계획에 필요한 결정이 모두 정해져 있다면 계획 작성을 이어간다. Milestone 전체에서 사용자만 결정할 항목이 더 이상 없을 때만 roadmap update 흐름으로 `구현 잠금` 상태를 `해제`로 갱신한다. 현재 요청에 직접 걸리는 결정이 필요하면 그 항목만 체크리스트로 남기고 사용자에게 확인한다.
- 사용자 검토, 제품 선택, 우선순위 결정처럼 사용자가 해야 하는 항목은 구현 계획의 실행 checklist로 쓰지 않는다. 현재 구현에 직접 필요하면 plan 생성을 멈추고 `결정 필요`로 남기며, 직접 필요하지 않으면 `작업 컨텍스트``범위 결정 근거`에만 기록한다.
- 기능 Task에 `검증:`이 있으면 구현 계획의 같은 plan item 안에 해당 검증을 포함한다. 검증이 명시되지 않은 기능 Task에는 억지 검증 항목을 만들지 말고, 필요한 일반 빌드/회귀 확인만 최종 검증에 둔다.
- 선택한 활성 Milestone 범위에 속하는 구현 계획이면 `{task_group}``m-<milestone-slug>`로 정한다. `<milestone-slug>`는 선택한 Milestone 경로의 파일명에서 `.md`를 제거한 값이다.
- 같은 Milestone에서 split work가 필요하면 기존 split 규칙 그대로 `agent-task/m-<milestone-slug>/<subtask_dir>/` 아래에 계획 파일을 만든다.
- roadmap/current 파일이 없으면 기존 task routing 규칙대로 진행한다.
Use short snake_case task group names for non-roadmap work, e.g. `api_refactor`.
Before choosing plan files or task directory names, apply the split decision policy above. When the policy allows a single plan, write active files directly under `agent-task/{task_group}/` and record the exception rationale. When the policy requires multiple plans, choose one shared `{task_group}` and `{subtask_dir}` names using the task directory naming rules above. Do not put multiple active plan files in one active task directory, and do not mix split subtask directories with active plan/review files directly in the parent task group.
## Step 2 - Analyze Before Writing
Complete all items below before creating 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`.
- Count existing `agent-task/{task_name}/user_review_*.log`; call it `U`. If `USER_REVIEW.md` exists in that same directory and the user explicitly decided to resume planning, rename `USER_REVIEW.md` to `user_review_U.log`.
The new plan number is the count of `plan_*.log` after archiving.
## Step 5 - Write Plan File
Header line must be exactly:
```markdown
<!-- task={task_name} plan={N} tag={TAG} -->
```
Required sections:
- Title.
- `이 파일을 읽는 구현 에이전트에게`: warn that filling implementation-owned `CODE_REVIEW-*-G??.md` sections is mandatory. Tell the implementer to run verification, fill actual notes/output, keep active files in place, and report ready for review; finalization is code-review-skill only.
- `배경`: 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 implementation/verification unit; if the roadmap feature Task has `검증:`, keep that verification in the same checklist item instead of making a separate completion-criteria item. Include one item for whole-plan intermediate/final verification only when it is not already covered by the feature items, and make the final item exactly: `- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.` Copy this checklist into the review stub's `구현 체크리스트` section with the same item text and order.
- One item per change: `### [TAG-1] Title`, `TAG-2`, etc.
- `수정 파일 요약`: table mapping files to item ids.
- `최종 검증`: runnable commands and expected outcome. 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이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [{TAG}-1] {item description} | [ ] |
| [{TAG}-2] {item description} | [ ] |
## 구현 체크리스트
{copy the plan's 구현 체크리스트 items exactly, preserving order and checkbox text}
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [ ] active `CODE_REVIEW-*-G??.md``code_review_{review_lane}_GNN_N.log`로 아카이브한다.
- [ ] active `PLAN-*-G??.md``plan_{build_lane}_GNN_M.log`로 아카이브한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/``agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md``CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 리뷰어를 위한 체크포인트
{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`.
- Milestone-linked work uses `agent-task/m-<milestone-slug>/` as the task group; non-roadmap task groups do not start with `m-`.
- Both first lines match `<!-- task={task_name} plan={N} tag={TAG} -->`.
- Previous active files, if any, were archived with correct numeric suffixes.
- If resuming from `USER_REVIEW.md`, it was archived to `user_review_N.log` and the user decision was recorded in the new plan.
- 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.

View 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."

View 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 갱신, 로드맵에 추가, 로드맵 작업 추가, 로드맵 기능 추가, 로드맵 Epic 추가, 로드맵 에픽 추가, 로드맵 Task 추가, 로드맵 태스크 추가, 로드맵 테스크 추가, 로드맵 TODO 추가, 마일스톤에 추가, 마일스톤 추가, 마일스톤 갱신, 마일스톤 아카이브, phase 추가, phase 변경, 페이즈 추가, 페이즈 변경, 현재 마일스톤 변경, 로드맵 한국어 전환, 로드맵 번역 | `agent-ops/skills/common/update-roadmap/SKILL.md` |
| 지금 작업이 뭐지?, 현재 작업 분석, 어디까지 했지?, 로드맵상 현 위치, 현재 마일스톤 위치, current 기준 breadcrumb | `agent-ops/skills/common/analyze-roadmap-position/SKILL.md` |
| 계획 세워줘, 계획 작성해, 계획 만들어줘, 구현 계획, PLAN.md, plan, plan 작성해, plan 만들어줘 | `agent-ops/skills/common/plan/SKILL.md` |
| 코드 리뷰해줘, 리뷰 진행해, 리뷰해줘, code review, CODE_REVIEW.md, 리뷰 루프 | `agent-ops/skills/common/code-review/SKILL.md` |
| 커밋해줘, 푸시해줘, commit, push, 반영해줘 | `agent-ops/skills/common/commit-push/SKILL.md` |
| agent-ops 싱크해, agent-ops 동기화해, agentic-framework에 올려줘, agent-ops를 [프로젝트]로 싱크해 | `agent-ops/skills/common/sync-push/SKILL.md` |
| agent-ops pull해, agent-ops 가져와, agentic-framework에서 가져와, agent-ops 내려받아 | `agent-ops/skills/common/sync-pull/SKILL.md` |
| 도메인 업데이트, domain rule 갱신, 도메인 검토, domain 스캔 | `agent-ops/skills/common/update-domain-rule/SKILL.md` |

View file

@ -0,0 +1,40 @@
---
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-Ops 관리 block이 있고 그 안에 `agent-task/archive/**``agent-ops/roadmap/archive/**`가 포함되어 있는가
- [ ] `.claude/settings.json`, `opencode.json``agent-task/archive/**` hard deny가 있고 `agent-ops/roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
- [ ] 현재 프로젝트에 기존 `agent-ops/roadmap/archive/**` hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
- [ ] agentic-framework의 AI ignore / permission 파일은 수정되거나 stage되지 않았는가
## 금지 사항
- sync.sh 를 거치지 않고 직접 파일을 복사하지 않는다

View file

@ -0,0 +1,101 @@
---
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 파일은 대상 프로젝트의 기존 내용을 덮어쓰지 않고, Agent-Ops 관리 block 또는 Agent-Ops 전용 permission key만 보강한다
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` 내용으로 교체한다.
## AI Ignore / Permission 재적용
- 이 절차는 agentic-framework 원본 프로젝트에서 대상 프로젝트로 push할 때와 `--pull`로 agentic-framework에서 현재 프로젝트로 내려받을 때만 적용한다.
- 일반 프로젝트에서 agentic-framework로 올리는 push에서는 AI ignore / permission 파일을 수정하거나 stage하지 않는다.
- `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`는 사용자 영역을 수정하지 않고 아래 관리 block만 추가하거나 교체한다.
```text
# BEGIN Agent-Ops managed ignore
agent-task/archive/**
agent-ops/roadmap/archive/**
# END Agent-Ops managed ignore
```
- 관리 block 밖의 기존 ignore 항목은 사용자 소유로 보고 삭제, 정렬, 중복 제거하지 않는다.
- `.claude/settings.json``opencode.json`은 기존 사용자 설정을 보존하고 `agent-task/archive/**` hard read/glob deny만 보강한다.
- `agent-ops/roadmap/archive/**`는 필요한 경우 링크로 읽을 수 있어야 하므로 `.claude/settings.json`이나 `opencode.json`의 hard read/glob deny로 두지 않는다.
- 대상 프로젝트에 기존 `agent-ops/roadmap/archive/**` hard read/glob deny가 있으면 init-agent-ops 표준에 맞게 제거한다.
- `opencode.json`의 watcher ignore에는 `agent-task/archive/**``agent-ops/roadmap/archive/**`를 둘 수 있다.
```bash
agent-ops/bin/sync.sh [target]
```
푸시 대상 path는 항상 `agent-ops/.version`, `agent-ops/bin`, `agent-ops/rules/common`, `agent-ops/skills/common`, `AGENT_OPS_ENTRY_FILES`의 진입 파일로 제한한다. 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-Ops 관리 block이 있고 그 안에 `agent-task/archive/**``agent-ops/roadmap/archive/**`가 포함되어 있는가
- [ ] framework에서 대상 프로젝트로 push한 경우, `.claude/settings.json``opencode.json``agent-task/archive/**` hard deny가 있고 `agent-ops/roadmap/archive/**` hard read/glob deny가 남아 있지 않은가
- [ ] 대상 프로젝트에 기존 `agent-ops/roadmap/archive/**` hard deny가 있으면 init-agent-ops 표준에 맞게 제거했는가
- [ ] 일반 프로젝트에서 agentic-framework로 push한 경우, AI ignore / permission 파일이 agentic-framework에 유입되지 않았는가
- [ ] 대상 repo에 commit/push 된 path가 방향별 허용 범위로 제한되었는가
## 금지 사항
- sync.sh 를 거치지 않고 직접 파일을 복사하지 않는다

View 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 파일 갱신만 담당한다

View file

@ -0,0 +1,355 @@
---
name: update-roadmap
version: 1.19.0
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가/갱신, phase/페이즈 변경 요청에 사용한다. Roadmap-Phase-Milestone scaffold에서 target 없는 신규 작업의 규모를 판정하고 기존 Phase/Milestone/Epic/Task를 검색해 upsert한 뒤, 없을 때만 새 항목을 만들고 current.md 동기화, runtime m-task 완료 이벤트 반영, 완료 후보 검토중 전환, 승인된 archive 이동을 처리한다.
---
# 로드맵 업데이트
## 목적
기존 `agent-ops/roadmap/` 구조를 현재 프로젝트 방향과 진행 상태에 맞게 갱신한다.
표준 구조는 `ROADMAP.md -> phase/<phase-slug>/PHASE.md -> phase/<phase-slug>/milestones/<milestone-slug>.md`다.
archive도 같은 Phase scaffold를 유지하며 `archive/phase/<phase-slug>/...` 아래에 둔다.
로드맵 전체를 매 작업마다 읽지 않도록 유지하면서, `current.md`의 활성 Phase와 활성 Milestone 창이 실제 작업 후보 목록으로 동작하게 한다.
Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서로 유지한다.
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.
## 언제 호출할지
- 사용자가 "로드맵 업데이트", "마일스톤 갱신", "phase 변경", "현재 활성 마일스톤 바꿔줘"라고 요청할 때
- 사용자가 "로드맵에 추가", "로드맵 작업 추가", "로드맵 기능 추가", "로드맵 Epic/Task 추가", "로드맵 에픽/태스크 추가", "마일스톤에 추가", "마일스톤 추가"처럼 로드맵에 새 내용을 넣어 달라고 요청할 때
- Milestone 완료, 보류, 폐기, 신규 추가가 필요할 때
- Phase 완료, 보류, 폐기, 신규 추가가 필요할 때
- 완료 또는 폐기된 Phase/Milestone을 archive로 이동해야 할 때
- 런타임이 `m-<milestone-slug>` task group의 PASS 완료 이벤트를 Milestone에 반영해야 할 때
- 특정 기능이나 작업을 새 Milestone, 기존 Milestone의 Epic, 기존 Epic의 Task 중 적절한 위치에 추가해야 할 때
- 활성 Phase/Milestone 창에 포함할 목록이 달라졌을 때
- 기존 로드맵을 `phase/<phase-slug>/PHASE.md` scaffold로 마이그레이션하거나 표준화해야 할 때
## 입력
- `mode`: `status` / `milestone` / `phase` / `replan` / `sync` / `concretize` / `archive` 중 하나 (선택, 요청에서 추론 가능)
- `target-phase`: 갱신할 Phase 이름, slug, 파일 경로 (선택)
- `target-milestone`: 갱신할 Milestone 이름, slug, 파일 경로 (선택)
- `active-phases`: 활성 Phase 창에 둘 Phase 이름, slug, 파일 경로 목록 (선택)
- `active-milestones`: 활성 Milestone 창에 둘 Milestone 이름, slug, 파일 경로 목록 (선택)
- `new-feature`: 추가할 기능, 작업, 또는 새 Milestone 설명 (선택)
- `placement`: 새 작업 배치 위치. 예: `<phase-name> 안`, `<milestone-name> 안`, `<epic-id> 아래`, `<item-id> 앞`, `<item-id> 뒤`, `auto` (선택)
- `placement-unit`: 삽입 단위. `phase` / `milestone` / `epic` / `task` / `subtask` / `auto` 중 하나 (선택)
- `target-status`: 전환할 Phase/Milestone 상태. `[스케치]` / `[계획]` / `[진행중]` / `[검토중]` / `[완료]` / `[보류]` / `[폐기]` 중 하나 (선택)
- `lock-state`: Milestone 구현 잠금 상태. `잠금` / `해제` 중 하나 (선택)
- `decision-needed`: `구현 잠금`에 남길 사용자만 결정할 수 있는 질문 목록 (선택)
- `evidence`: 완료 판단에 사용할 파일, PR, 테스트, 커밋, 사용자 설명 (선택)
- `review-state`: 완료 리뷰 상태. `요청됨` / `승인됨` / `보완 필요` / `보류` / `폐기` 중 하나 (선택)
- `review-comment`: 완료 리뷰에 남길 사용자 확인, 보완, 보류, 폐기 방향성 (선택)
- `origin-task`: 런타임 완료 이벤트가 전달한 `agent-task/m-<milestone-slug>` 또는 `agent-task/m-<milestone-slug>/<subtask_dir>` 형식의 원래 active task 경로. 이벤트가 최종 archive 경로만 갖고 있으면 런타임이 이 형식으로 정규화해 전달한다 (선택)
- `archive-date`: Phase/Milestone 아카이브 날짜. 없으면 현재 날짜를 사용한다 (선택)
## 표준 구조
```text
agent-ops/roadmap/
ROADMAP.md
current.md
phase/
<phase-slug>/
PHASE.md
milestones/
<milestone-slug>.md
archive/
phase/
<phase-slug>/
PHASE.md
milestones/
<milestone-slug>.md
```
- `ROADMAP.md`는 전체 목표와 Phase 흐름만 담는다.
- `PHASE.md`는 해당 Phase의 목표, 상태, Milestone 흐름, Phase 경계를 담는다.
- Milestone 문서는 해당 Phase 하위 `milestones/`에 둔다.
- 완료된 Phase는 `archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
- 진행중 Phase 안에서 완료된 Milestone은 `archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동하고, 활성 `PHASE.md`에는 짧은 archive 링크를 남긴다.
- archive `PHASE.md`는 Phase 자체가 완료/폐기될 때만 만든다. 진행중 Phase의 완료 Milestone만 archive된 경우에는 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
- `<phase-slug>``<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용한다.
- `current.md`는 활성 Phase와 활성 Milestone을 모두 가리킨다.
- `current.md`에는 archive 경로를 넣지 않는다.
- `current.md`에는 `[완료]` 또는 `[폐기]` Phase/Milestone을 남기지 않는다. 완료 후보는 사용자 승인 전까지 `[검토중]`으로 둔다.
## 상태와 id
- 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
- 기존 비표준 상태 표기는 갱신 범위에 포함될 때 표준 상태 표기로 정리한다.
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 `agent-task` 구현 계획 생성과 코드 구현 대상으로 삼지 않는다.
- `[스케치]` 항목은 `[계획]`으로 승격하기 위한 `승격 조건`, 사용자 결정, 범위 경계, 후속 Milestone 후보를 정리한다.
- `[계획]` 이상 Milestone에서 `승격 조건` 섹션은 선택 사항이다. 섹션이 없거나 `- 없음`이면 템플릿 오류로 보지 않는다.
- `[스케치]``[계획]`으로 전환할 때는 `승격 조건`의 미정 항목이 해소되고, 목표, 범위, 기능 Task, 직접적인 사용자 결정 항목, 후속 구현 단위가 구현 계획을 만들 수 있을 만큼 정리되었는지 확인한다.
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 정리되어 구현 계획을 만들 수 있는 상태다.
- `[검토중]`은 모든 기능 Task와 Task 안에 명시된 검증이 충족된 것으로 보이나, 사용자 최종 확인과 archive 승인이 남은 완료 후보 상태다.
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
- Task는 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식으로 작성한다.
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
- 사용자가 epic-id 또는 item-id를 언급하면 해당 항목을 우선 anchor로 삼고, 기존 id는 명시적 요청 없이 바꾸지 않는다.
## 로딩 원칙
- 일반 갱신은 `current.md`, 관련 활성 Phase, 관련 활성 Milestone을 우선 읽는다.
- `ROADMAP.md`는 Phase 흐름, 전체 구조, 활성 범위 밖 작업, 전체 재계획, archive 링크 갱신이 필요할 때 읽는다.
- `agent-ops/roadmap/archive/**`는 일반 작업이나 sync에서 읽지 않는다.
- archive 모드에서 이동 대상이 아직 활성 경로에 있으면 그 대상 문서는 읽을 수 있다.
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 요청이면 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 archive 문서만 읽는다.
## 템플릿
- `ROADMAP.md`: `agent-ops/skills/common/_templates/roadmap-template.md`
- `current.md`: `agent-ops/skills/common/_templates/roadmap-current-template.md`
- `PHASE.md`: `agent-ops/skills/common/_templates/roadmap-phase-template.md`
- Milestone: `agent-ops/skills/common/_templates/roadmap-milestone-template.md`
## 구현 잠금
- `구현 잠금`은 승인 절차가 아니라 사용자 결정이 필요한지 표시하는 얇은 상태다.
- 사용자만 결정할 수 있는 제품 방향, 범위, 우선순위, 책임 경계가 남아 있으면 `잠금`으로 두고 `결정 필요` 체크리스트에 질문을 적는다.
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선으로 기록한다.
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
- 잠금 상태 변경은 Milestone 완료 판정이 아니므로 `기능` Task를 자동 완료 처리하지 않는다.
- `[스케치]` Milestone은 `구현 잠금``해제`로 보이더라도 구현 계획과 코드 구현 대상이 아니다. 먼저 승격 조건을 충족해 `[계획]`으로 전환한다.
## 완료 리뷰와 검토중 상태
- Task 완료 또는 Milestone 갱신 후 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`인지 확인한다.
- 모두 충족된 것으로 보이면 Milestone을 `[완료]`로 바로 바꾸거나 archive로 이동하지 말고 `[검토중]`으로 바꾼다.
- `[검토중]`으로 바꿀 때는 Milestone 문서의 `완료 리뷰` 섹션을 만들거나 갱신한다.
- `완료 리뷰`에는 `상태: 요청됨`, `요청일`, 완료 근거 1~3줄, 사용자 최종 확인 항목, 리뷰 코멘트를 남긴다.
- 사용자가 승인하면 `완료 리뷰``상태: 승인됨`으로 바꾸고 Milestone 상태를 `[완료]`로 전환한 뒤 archive 모드를 수행한다.
- 사용자가 보완을 요구하면 `완료 리뷰``상태: 보완 필요`로 바꾸고 Milestone 상태를 `[진행중]`으로 되돌린다. 이때 보완 방향을 `완료 리뷰` 또는 `작업 컨텍스트`에 남기며 별도 reopen 상태는 만들지 않는다.
- 사용자가 보류 또는 폐기를 지시하면 `완료 리뷰`와 Milestone 상태를 각각 `보류`/`[보류]`, `폐기`/`[폐기]`로 맞춘다. `[폐기]`는 archive 대상이 될 수 있다.
- Phase는 하위 Milestone이 모두 `[완료]` 또는 `[폐기]`로 정리되고 Phase 목표도 충족된 것으로 보일 때 `[검토중]`으로 두고, 사용자 승인 후 `[완료]` 또는 `[폐기]`로 archive한다.
## Milestone task group 연동
- 런타임 완료 이벤트의 `origin-task`에서 `agent-task/` 다음 첫 path segment가 `m-<milestone-slug>`이면 Milestone 기반 plan/review 완료에서 온 요청으로 본다. `origin-task`는 archive 이동 전 active task 경로 또는 런타임이 그 형태로 정규화한 경로를 사용한다.
- `<milestone-slug>`는 활성 `agent-ops/roadmap/phase/*/milestones/<milestone-slug>.md`에서 정확히 하나만 찾아야 한다. archive Milestone은 target 후보가 아니다.
- target이 없거나 둘 이상이면 Milestone 내용을 추정해 수정하지 말고 target 불명확으로 보고한다.
- target이 확정되면 PASS evidence, `complete.log`, final archive path, archived plan/review log 경로, code-review 결과 요약을 근거로 해당 Milestone의 기능 Task를 갱신한다. target routing 자체는 완료 이벤트의 `m-<milestone-slug>` task group으로만 결정한다.
- 갱신 후 모든 기능 Task와 Task 안에 명시된 검증이 충족되면 `[검토중]` 전환과 `완료 리뷰` 요청 규칙을 적용한다.
- target Milestone이 `[스케치]`이면 완료 이벤트를 반영하지 말고 상태 불일치로 보고한다. `[스케치]`는 Milestone 기반 `agent-task` 완료 이벤트의 target이 될 수 없다.
## 삽입 단위 정책
| 삽입 단위 | 사용 기준 |
|-----------|-----------|
| 새 Phase | 독립적인 제품 진화 단계와 여러 Milestone 묶음이 필요하다 |
| 새 Milestone | 독립적인 목표와 기능 Task 묶음이 필요하고 Phase 흐름에 의미 있는 경계를 만든다 |
| 새 Epic | 기존 Milestone 안에서 여러 Task를 묶는 상위 capability 또는 산출물이다 |
| 새 Task | 기존 Epic 아래에 들어가는 완료 가능한 capability 또는 산출물이다. 검증이 필요한 경우에만 같은 Task 안에 붙인다 |
| 하위 작업 | 기존 Task를 완성하기 위한 구현 세부다. Milestone `기능`에는 하위 체크박스로 만들지 않고, plan 내부 체크리스트나 기존 Task의 `검증:`/설명 보강으로 다룬다 |
| 작업 컨텍스트/TODO | 사용자 결정 또는 조사/확인이 먼저 필요해 기능 Task로 확정하기 어렵다 |
- 먼저 요청 내용의 규모를 판정한다. 배치 위치를 찾기 전에 `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 단위를 고른다.
- 요청이 방향성, 문제의식, 컨셉, 운영 원칙 수준이고 기능 Task나 실행 범위가 아직 부족하면 새 항목의 상태는 `[스케치]`로 둔다.
- `[스케치]` Phase/Milestone을 만들 때는 `승격 조건``[계획]`으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 체크리스트로 남긴다.
- 가장 작은 충분한 단위 원칙을 따른다. 애매하면 새 Phase나 새 Milestone으로 키우지 말고, 기존 Milestone의 Epic/Task에 넣을 수 있는지 먼저 확인한다.
- 위치 지정이 있으면 anchor의 레벨을 먼저 확인한다.
- `<epic-id> 아래`는 해당 Epic 아래 Task로 넣는다.
- `<item-id> 앞/뒤`는 같은 Epic 안의 형제 Task로 넣는다.
- `<item-id> 아래`는 해당 Task의 설명 또는 `검증:`을 보강한다. 구현 세부나 테스트만 따로 떼어낸 하위 체크박스는 Milestone `기능` 아래에 만들지 않는다.
- `<phase-name> 안`은 새 Milestone 또는 기존 Milestone/Epic/Task 중 작업 성격에 맞는 단위로 배치한다.
- 위치 지정이 없으면 `auto`로 본다. `current.md`의 활성 창만으로 결정하지 않고, 필요한 경우 `ROADMAP.md`의 Phase 흐름까지 확인해 완료/검토중/진행중/계획/스케치 Phase를 비교한다.
- target 없는 신규 추가 요청은 요청 문장, 관련 파일/도메인 힌트, Phase 목표, Milestone 목표, 기존 Epic/Task, 선후 의존성, 상태, 활성 창을 비교해 가장 자연스러운 위치를 자동 판단한다.
- 자동 배치 후보가 여러 개이면 1순위와 2순위 후보를 비교하고, 선택한 Phase/Milestone/Epic/Task와 밀린 후보의 이유를 짧게 남긴다.
- 관련성이 비슷하면 `[진행중]` Milestone을 `[계획]` Milestone보다 우선하되, `[검토중]` Milestone은 리뷰 보완 요청이 아닌 신규 작업의 기본 배치 대상으로 삼지 않는다.
- 자동 배치한 경우 결과 보고에 선택한 삽입 단위, 위치, 판단 근거, 비교한 후보를 짧게 남긴다.
- 사용자 지정 위치가 Phase 목표, Milestone 범위 제외, 선후 의존성과 충돌하면 수정 전에 사용자에게 확인한다.
## 레벨별 탐색과 upsert 정책
target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다.
1. **요청 정규화**
- 요청 문장에서 기능명, 목표, 산출물, 관련 경로/도메인, 완료 기대, 제약, 명시 anchor를 뽑는다.
- 사용자가 Phase/Milestone/Epic/Task/id/path를 명시했으면 그 anchor를 우선 후보로 둔다.
2. **규모 판정**
- 여러 Milestone을 묶는 제품/운영 단계면 Phase 규모다.
- 독립 목표, 기능 Task 묶음, 여러 Epic이 필요한 결과면 Milestone 규모다.
- 컨셉은 충분히 크지만 구현 가능한 목표/범위/기능 Task가 아직 없으면 `[스케치]` Phase 또는 Milestone 후보로 둔다.
- 한 Milestone 안의 capability 묶음이면 Epic 규모다.
- Epic 아래에서 완료 가능한 단일 capability 또는 산출물이면 Task 규모다. 검증이 필요한 경우에만 같은 Task 안에 포함한다.
- Task를 완성하기 위한 구현 세부면 subtask 규모다. roadmap에는 하위 체크박스로 기록하지 않고, 구현 계획 내부 또는 기존 Task 보강으로 처리한다.
- 조사, 결정, 보류 질문이면 작업 컨텍스트/TODO 규모다.
3. **레벨별 탐색**
- Phase 후보를 먼저 찾는다. `current.md`의 활성 Phase를 우선 보되, target이 없거나 활성 범위 밖 가능성이 있으면 `ROADMAP.md`의 Phase 흐름도 본다.
- 선택한 Phase 안에서 Milestone 후보를 찾는다. 활성 Milestone을 우선 보되, 요청이 계획 Milestone 목표와 더 직접 맞으면 계획 Milestone도 후보로 둔다.
- 선택한 Milestone 안에서 Epic 후보를 찾는다. `기능`의 Epic heading, 목표 설명, Task 묶음을 비교한다. 기존 문서가 `필수 기능`을 쓰면 갱신 시 `기능`으로 정규화한다.
- 선택한 Epic 안에서 Task 후보를 찾는다. item-id, 문장 의미, Task 안의 검증 문구, 관련 경로를 비교한다.
- archive 문서는 기본 탐색 대상이 아니다. 사용자가 과거 기록 비교를 명시했거나 완료 내용 확인이 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 문서만 읽는다.
4. **중복/업데이트 판정**
- 같은 id, 같은 제목, 같은 목표, 같은 관련 경로, 같은 Task 안의 검증 문구, 또는 같은 산출물을 다루면 동일/유사 후보로 본다.
- 동일 항목이면 새로 만들지 않고 기존 Phase/Milestone/Epic/Task를 업데이트한다.
- 기존 항목의 범위를 보강하는 내용이면 해당 항목의 설명, Task 안의 검증 문구, 작업 컨텍스트 중 알맞은 곳에 병합한다.
- 기존 항목과 충돌하거나 범위 제외를 건드리면 수정 전에 사용자에게 확인한다.
- 같은 레벨에 적절한 후보가 없을 때만 새 항목을 만든다. 새 항목도 판정한 규모보다 크게 만들지 않는다.
- 부모 레벨 후보는 있고 판정 규모의 항목만 없으면, 부모 아래에 판정 규모의 새 항목을 만든다. 부모 레벨도 없을 때만 필요한 부모 항목을 함께 만든다.
## archive 정책
### Milestone archive
- 대상 Milestone이 `[완료]` 또는 `[폐기]`인지 확인한다.
- `[검토중]` Milestone은 archive하지 않는다. 사용자 완료 승인 또는 폐기 지시가 있으면 먼저 `[완료]` 또는 `[폐기]`로 바꾼 뒤 archive한다.
- 대상 파일을 `agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에서 `agent-ops/roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동한다.
- 활성 `PHASE.md`의 Milestone 흐름에는 `[완료]` 또는 `[폐기]` 항목을 남기고, 경로는 archive 경로로 바꾼다.
- `current.md`의 활성 Milestone에서는 제거한다.
- `ROADMAP.md`는 Phase 상태나 경로가 바뀌지 않으면 수정하지 않는다.
- 이동한 archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.
### Phase archive
- Phase 전체가 `[완료]` 또는 `[폐기]`인지 확인한다.
- `[검토중]` Phase는 archive하지 않는다. 사용자 완료 승인 또는 폐기 지시가 있으면 먼저 `[완료]` 또는 `[폐기]`로 바꾼 뒤 archive한다.
- `agent-ops/roadmap/phase/<phase-slug>/PHASE.md``agent-ops/roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동한다.
- 해당 Phase의 하위 Milestone도 `archive/phase/<phase-slug>/milestones/` 아래로 이동한다.
- `ROADMAP.md`의 Phase 흐름에는 해당 Phase 항목을 남기고, 상태와 경로를 archive `PHASE.md`로 바꾼다.
- `current.md`의 활성 Phase와 활성 Milestone에서는 해당 Phase와 하위 Milestone을 제거한다.
- archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.
## 실행 절차
1. **갱신 범위 결정**
- 요청에서 mode, 대상 Phase/Milestone, placement, placement-unit을 추론한다.
- 런타임 완료 이벤트의 `origin-task` task group이 `m-<milestone-slug>`이면 `target-milestone`을 활성 Milestone 경로 매칭으로 확정한다.
- 구조 전환, 템플릿 보정, current 동기화는 `sync`로 본다.
- 사용자 승인 이후의 완료/폐기 이동은 `archive`로 본다.
- 새 기능 배치, Epic/Task 추가는 `milestone` 또는 `phase`로 본다.
- "로드맵에 추가"처럼 target이 없는 신규 작업 요청은 `placement=auto`, `placement-unit=auto`, `new-feature=<요청 내용>`으로 본다.
2. **요청 정규화와 규모 판정**
- 요청에서 기능명, 목표, 관련 경로, 명시 anchor, 완료 기대, 제약을 추출한다.
- `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 규모를 판정한다.
- 동일/유사 항목이 이미 있으면 신규 추가가 아니라 업데이트 후보로 기록한다.
3. **레벨별 후보 탐색**
- `current.md`의 활성 Phase와 활성 Milestone 후보를 확인한다.
- target이 명시된 경우 대상 Phase의 `PHASE.md`를 읽고 Milestone 흐름과 Phase 경계를 확인한다.
- target이 없거나 활성 창 밖 배치 가능성이 있으면 `ROADMAP.md`의 Phase 흐름을 확인하고, 관련성이 높은 Phase 문서를 읽는다.
- 대상 또는 후보 Milestone 문서의 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. 기존 문서에 `필수 기능`/`완료 기준`이 분리되어 있으면 갱신 범위에서 `기능` Task로 흡수할 후보를 기록한다.
- Phase -> Milestone -> Epic -> Task 순서로 내려가며 같은 레벨의 동일/유사 후보를 먼저 찾는다.
- `current.md`에 archive 경로가 있으면 읽지 말고 제거 대상으로 기록한다.
- 필요한 경우에만 `ROADMAP.md`를 읽어 전체 Phase 흐름을 확인한다.
4. **스케치 승격 판단**
- `target-status=[계획]`, `mode=concretize`, 또는 사용자가 "구체화", "계획으로 올려"처럼 요청하면 `[스케치] -> [계획]` 승격 검토로 본다.
- 대상이 `[스케치]`가 아니면 일반 상태 갱신이나 Milestone 갱신으로 처리한다.
- 대상이 `[스케치]`이면 `승격 조건`, `구현 잠금`, `목표`, `범위`, `기능`, `작업 컨텍스트`를 확인한다.
- `승격 조건` 체크리스트가 남아 있거나 구현 계획에 직접 필요한 사용자 결정이 남아 있으면 상태를 `[스케치]`로 유지하고, 부족한 항목을 `승격 조건` 또는 `결정 필요`에 보강한다.
- 구현 가능한 목표, 범위, 기능 Task, 직접 결정 항목, 후속 구현 단위가 정리되면 상태를 `[계획]`으로 전환하고, `승격 조건`은 충족 요약으로 남기거나 `- 없음`으로 정리한다.
- 승격은 구현 완료가 아니므로 `기능` Task를 자동 완료 처리하지 않는다.
5. **변경 내용 작성**
- `ROADMAP.md`는 전체 목표, Phase 흐름, 로딩 정책이 바뀔 때만 수정한다.
- `current.md`는 활성 Phase/Milestone 창이 바뀔 때 수정한다.
- `PHASE.md`는 Phase 목표, 상태, Milestone 흐름, Phase 경계가 바뀔 때 수정한다.
- Milestone 문서는 목표, 상태, 승격 조건, 구현 잠금, 범위, Epic/Task, Task 안의 검증 문구, 완료 리뷰, 범위 제외, 작업 컨텍스트가 바뀔 때 수정한다.
- 동일/유사 후보가 있으면 기존 항목을 업데이트하고 중복 항목을 만들지 않는다.
- 새 Milestone은 해당 Phase의 `milestones/` 아래에 만든다.
- 새 `[스케치]` Milestone은 `승격 조건` 섹션을 포함하고 `구현 잠금``잠금`으로 둔다.
- 새 Epic은 `기능` 아래 `### Epic: [epic-id] <이름>`으로 만든다.
- 새 Task는 관련 Epic 아래 `- [ ] [item-id] 설명`으로 만든다. 검증이 필요한 경우에만 같은 항목에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
- 새 항목은 레벨별 탐색에서 적절한 기존 후보가 없을 때만 만든다.
- 완료 체크는 evidence가 있을 때만 `[x]`로 바꾼다.
- 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이면 Milestone 상태를 `[검토중]`으로 바꾸고 `완료 리뷰`에 리뷰 요청과 근거를 남긴다.
- `[검토중]` 전환만으로 archive 이동, `current.md` 제거, archive 링크 변경을 수행하지 않는다.
- 사용자 승인 근거가 있으면 `[검토중]``[완료]`로 전환하고 archive 모드를 수행할 수 있다.
6. **검증**
- `current.md`의 활성 Phase/Milestone 경로가 실제 파일을 가리키는지 확인한다.
- `current.md`의 활성 항목이 archive 경로를 가리키지 않는지 확인한다.
- `current.md`의 활성 항목이 `[완료]` 또는 `[폐기]` 상태로 남아 있지 않은지 확인한다.
- `ROADMAP.md`의 Phase 경로가 실제 `PHASE.md` 파일을 가리키는지 확인한다.
- 각 `PHASE.md`의 Milestone 경로가 실제 파일을 가리키는지 확인한다.
- 상태 표기가 표준값인지 확인한다.
- `[스케치]` Milestone에 `승격 조건`이 있고 `구현 잠금``잠금`인지 확인한다.
- `[계획]` 이상 Milestone에 `승격 조건` 섹션이 없더라도 오류로 보지 않는다. 섹션이 있으면 `- 없음` 또는 승격 충족 요약인지 확인한다.
- `[스케치] -> [계획]` 전환을 수행했다면 승격 조건 해소 근거가 Milestone 내용이나 결과 보고에 남았는지 확인한다.
- `[검토중]` Milestone이 archive 경로로 이동되지 않았는지 확인한다.
- 모든 기능 Task와 Task 안에 명시된 검증이 `[x]`인 Milestone에는 `완료 리뷰` 섹션과 사용자 리뷰 요청이 있는지 확인한다.
- Epic heading과 Task id 형식이 맞는지 확인한다.
- 요청 규모가 판정되었고 결과 보고에 남았는지 확인한다.
- 동일/유사 기존 항목을 검색했고 신규/업데이트 판정이 결과 보고에 남았는지 확인한다.
- 자동 배치한 신규 작업이면 선택한 후보와 밀린 후보의 근거가 결과 보고에 포함되는지 확인한다.
- `git diff --check`로 공백 오류를 확인한다.
7. **결과 보고**
- 수정한 파일 목록
- 요청 규모 판정과 근거
- Phase -> Milestone -> Epic -> Task 탐색 경로와 후보
- 신규 추가인지 기존 항목 업데이트인지
- 변경된 Phase / Milestone / 상태
- 신규 작업의 삽입 단위와 배치 위치
- 자동 배치한 경우 비교한 후보와 선택 근거
- current.md 활성 창 변경 사항
- 완료 리뷰 상태와 사용자 확인 필요 항목
- 런타임 완료 이벤트의 `origin-task``m-<milestone-slug>`이면 원래 active task 경로와 매칭된 target Milestone 또는 target 불명확 사유
- archive 모드이면 이동 경로와 남긴 링크
- 확인 필요로 남긴 항목
## 출력 형식
```markdown
## 업데이트 완료
- 모드: <status | milestone | phase | replan | sync | concretize | archive>
- 수정 파일:
- agent-ops/roadmap/ROADMAP.md
- agent-ops/roadmap/current.md
- agent-ops/roadmap/phase/<phase-slug>/PHASE.md
- agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md
- agent-ops/roadmap/archive/phase/<phase-slug>/... (archive 모드)
## 변경 사항
- Phase: <변경 없음 | 요약>
- Milestone: <변경 없음 | 요약>
- 삽입 단위: <Phase | Milestone | Epic | Task | 하위 작업 | 작업 컨텍스트/TODO | 변경 없음>
- 규모 판정: <phase | milestone | epic | task | subtask | context | 변경 없음> - <근거>
- 탐색 경로: <Phase 후보 -> Milestone 후보 -> Epic 후보 -> Task 후보 | 해당 없음>
- 신규/업데이트 판정: <신규 생성 | 기존 항목 업데이트 | 변경 없음> - <동일/유사 후보 근거>
- 배치: <사용자 지정 위치 반영 | 자동 배치 위치와 근거 | 변경 없음>
- 배치 후보: <자동 배치 1순위/2순위 후보와 선택/제외 근거 | 해당 없음>
- 템플릿 보정: <ROADMAP | current.md | PHASE | Milestone | 이미 일치 | 변경 없음>
- 구현 잠금: <잠금 유지 | 잠금 추가 | 해제 | 변경 없음>; 결정 필요: <없음 | 항목 요약>
- 승격 조건: <해당 없음 | 추가/수정/미충족 유지/충족 요약>
- 완료 리뷰: <변경 없음 | 요청됨 | 승인됨 | 보완 필요 | 보류 | 폐기>
- runtime m-task 라우팅: <해당 없음 | origin-task -> target Milestone | target 불명확>
- 활성 항목: <변경 없음 | Phase/Milestone 추가/제거 요약>
- 아카이브: <변경 없음 | 이동 경로와 남긴 링크>
- 상태: <변경 없음 | 이전 -> 이후>
- Epic/Task: <추가/수정/완료/제거 요약>
## TODO 항목
- <확인이 필요한 항목> (해당 시)
```
## 금지 사항
- 로드맵 파일이 없는데 새 구조를 임의로 만들지 않는다. 이 경우 `create-roadmap`을 사용한다.
- evidence 없이 Phase, Milestone, Epic, Task를 `[완료]` 또는 `[검토중]`으로 처리하지 않는다.
- 전체 `ROADMAP.md`를 모든 작업의 필수 로딩 파일로 만들지 않는다.
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 남기지 않는다.
- `current.md`에 개인별 현재 작업 위치나 완료 상태를 남기지 않는다.
- `current.md``agent-ops/roadmap/archive/**` 경로를 남기지 않는다.
- archive 문서를 명시 요청 없이 읽거나 최신 템플릿으로 재포맷하지 않는다.
- 완료된 Phase/Milestone 기록을 삭제하지 않는다.
- Epic과 Task를 별도 파일로 분리하지 않는다.
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
- 사용자만 결정할 수 있는 항목이 남아 있는데 Milestone의 `구현 잠금``해제`로 바꾸지 않는다.
- 사용자가 지정한 Phase/Milestone/Epic/Task anchor를 무시하지 않는다.
- 사용자가 명시하지 않은 기존 epic-id나 item-id를 바꾸지 않는다.

17
opencode.json Normal file
View file

@ -0,0 +1,17 @@
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": {
"agent-task/archive/**": "deny"
},
"glob": {
"agent-task/archive/**": "deny"
}
},
"watcher": {
"ignore": [
"agent-task/archive/**",
"agent-ops/roadmap/archive/**"
]
}
}