sync: agent-ops from agentic-framework v1.1.71
This commit is contained in:
parent
a90d15f85e
commit
4d047e6344
12 changed files with 237 additions and 47 deletions
|
|
@ -18,6 +18,7 @@
|
||||||
# 프로젝트 간 잠금
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
||||||
|
- 외부 의존 잠금 생성/동기화 요청은 `.agent-roadmap-sync/locks.yaml`이 없어도 `update-roadmap`이 생성한다.
|
||||||
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
# 프로젝트 간 잠금
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
||||||
|
- 외부 의존 잠금 생성/동기화 요청은 `.agent-roadmap-sync/locks.yaml`이 없어도 `update-roadmap`이 생성한다.
|
||||||
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
# 프로젝트 간 잠금
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
||||||
|
- 외부 의존 잠금 생성/동기화 요청은 `.agent-roadmap-sync/locks.yaml`이 없어도 `update-roadmap`이 생성한다.
|
||||||
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
# 프로젝트 간 잠금
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
||||||
|
- 외부 의존 잠금 생성/동기화 요청은 `.agent-roadmap-sync/locks.yaml`이 없어도 `update-roadmap`이 생성한다.
|
||||||
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
# 프로젝트 간 잠금
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
||||||
|
- 외부 의존 잠금 생성/동기화 요청은 `.agent-roadmap-sync/locks.yaml`이 없어도 `update-roadmap`이 생성한다.
|
||||||
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1.1.70
|
1.1.71
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,20 @@ LOCKS_FILE="${AGENT_ROADMAP_LOCKS_FILE:-$WORKSPACE_ROOT/.agent-roadmap-sync/lock
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
Usage: roadmap-dependency-checker.sh <lock-id> [locks.yaml]
|
Usage: roadmap-dependency-checker.sh <lock-id> [locks.yaml]
|
||||||
|
roadmap-dependency-checker.sh --find-milestone <identity> [locked|rely-on|both] [locks.yaml]
|
||||||
|
|
||||||
Validates locked, rely-on.target, and rely-on.status for <lock-id>.
|
Validates locked, rely-on.target, and rely-on.status for <lock-id>.
|
||||||
Prints true when every rely-on.status is enable.
|
Prints true when every rely-on.status is enable.
|
||||||
Prints false when at least one rely-on.status is disable.
|
Prints false when at least one rely-on.status is disable.
|
||||||
|
With --find-milestone, prints matching lock ids as locked:<id> or rely-on:<id>,
|
||||||
|
or none when the milestone identity is not referenced.
|
||||||
|
|
||||||
Exit codes:
|
Exit codes:
|
||||||
0 all dependencies are enabled
|
0 all dependencies are enabled
|
||||||
1 at least one dependency is still disabled
|
1 at least one dependency is still disabled
|
||||||
2 configuration, input, or parse error
|
2 configuration, input, or parse error
|
||||||
|
For --find-milestone, exit code 0 means the lookup completed; stdout is either
|
||||||
|
matching entries or none.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,17 +32,51 @@ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $# -lt 1 || $# -gt 2 ]]; then
|
MODE="check"
|
||||||
|
LOCK_ID=""
|
||||||
|
FIND_IDENTITY=""
|
||||||
|
FIND_DIRECTION="both"
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "--find-milestone" ]]; then
|
||||||
|
MODE="find"
|
||||||
|
if [[ $# -lt 2 || $# -gt 4 ]]; then
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
FIND_IDENTITY="$2"
|
||||||
|
if [[ -z "$FIND_IDENTITY" ]]; then
|
||||||
|
echo "error: milestone identity is required" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [[ $# -ge 3 ]]; then
|
||||||
|
case "$3" in
|
||||||
|
locked|rely-on|both)
|
||||||
|
FIND_DIRECTION="$3"
|
||||||
|
if [[ $# -eq 4 ]]; then
|
||||||
|
LOCKS_FILE="$4"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ $# -eq 3 ]]; then
|
||||||
|
LOCKS_FILE="$3"
|
||||||
|
else
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
elif [[ $# -lt 1 || $# -gt 2 ]]; then
|
||||||
usage >&2
|
usage >&2
|
||||||
exit 2
|
exit 2
|
||||||
|
else
|
||||||
|
LOCK_ID="$1"
|
||||||
|
if [[ -n "${2:-}" ]]; then
|
||||||
|
LOCKS_FILE="$2"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
LOCK_ID="$1"
|
if [[ "$MODE" == "check" && -z "$LOCK_ID" ]]; then
|
||||||
if [[ -n "${2:-}" ]]; then
|
|
||||||
LOCKS_FILE="$2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$LOCK_ID" ]]; then
|
|
||||||
echo "error: lock id is required" >&2
|
echo "error: lock id is required" >&2
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
@ -47,6 +86,106 @@ if [[ ! -r "$LOCKS_FILE" ]]; then
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$MODE" == "find" ]]; then
|
||||||
|
awk -v identity="$FIND_IDENTITY" -v direction="$FIND_DIRECTION" '
|
||||||
|
function trim(value) {
|
||||||
|
gsub(/\r/, "", value)
|
||||||
|
sub(/^[[:space:]]+/, "", value)
|
||||||
|
sub(/[[:space:]]+$/, "", value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
function unquote(value) {
|
||||||
|
value = trim(value)
|
||||||
|
sub(/[[:space:]]+#.*$/, "", value)
|
||||||
|
value = trim(value)
|
||||||
|
if (value ~ /^".*"$/ || value ~ /^'\''.*'\''$/) {
|
||||||
|
return substr(value, 2, length(value) - 2)
|
||||||
|
}
|
||||||
|
return trim(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset_entry() {
|
||||||
|
entry_id = ""
|
||||||
|
locked = ""
|
||||||
|
in_rely_on = 0
|
||||||
|
rely_count = 0
|
||||||
|
delete rely_targets
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish_entry( i) {
|
||||||
|
if (entry_id == "") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((direction == "both" || direction == "locked") && locked == identity) {
|
||||||
|
print "locked:" entry_id
|
||||||
|
found = 1
|
||||||
|
}
|
||||||
|
if (direction == "both" || direction == "rely-on") {
|
||||||
|
for (i = 1; i <= rely_count; i++) {
|
||||||
|
if (rely_targets[i] == identity) {
|
||||||
|
print "rely-on:" entry_id
|
||||||
|
found = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
found = 0
|
||||||
|
reset_entry()
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*($|#)/ {
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*-[[:space:]]*id:[[:space:]]*/ {
|
||||||
|
finish_entry()
|
||||||
|
reset_entry()
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*-[[:space:]]*id:[[:space:]]*/, "", value)
|
||||||
|
entry_id = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && /^[[:space:]]*locked:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*locked:[[:space:]]*/, "", value)
|
||||||
|
locked = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && /^[[:space:]]*rely-on:[[:space:]]*/ {
|
||||||
|
in_rely_on = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && in_rely_on && /^[[:space:]]*-[[:space:]]*target:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*-[[:space:]]*target:[[:space:]]*/, "", value)
|
||||||
|
rely_targets[++rely_count] = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_id != "" && in_rely_on && /^[[:space:]]*target:[[:space:]]*/ {
|
||||||
|
value = $0
|
||||||
|
sub(/^[[:space:]]*target:[[:space:]]*/, "", value)
|
||||||
|
rely_targets[++rely_count] = unquote(value)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
finish_entry()
|
||||||
|
if (!found) {
|
||||||
|
print "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$LOCKS_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
awk -v wanted="$LOCK_ID" '
|
awk -v wanted="$LOCK_ID" '
|
||||||
function trim(value) {
|
function trim(value) {
|
||||||
gsub(/\r/, "", value)
|
gsub(/\r/, "", value)
|
||||||
|
|
|
||||||
|
|
@ -67,18 +67,25 @@
|
||||||
|
|
||||||
## 프로젝트 간 잠금
|
## 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다.
|
- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다. 외부 의존 잠금을 생성하거나 동기화해야 하면 파일이 없어도 `update-roadmap`이 디렉터리와 파일을 만든다.
|
||||||
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
|
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
|
||||||
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
|
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
|
||||||
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
|
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
|
||||||
- `locked`와 `rely-on[].target`은 `<project>:agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
|
- `locked`와 `rely-on[].target`은 `<project>:agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
|
||||||
- "현재 마일스톤은 X 프로젝트 작업 뒤에 진행", "X 프로젝트 때문에 현재 작업 잠금", "의존성 설정해"처럼 대상 Milestone을 생략한 외부 의존 잠금 요청은 현재 프로젝트의 `current.md` 활성 Milestone을 잠긴 대상으로 삼는다.
|
- Milestone 경로가 `agent-ops/roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다. workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-ops/roadmap/...` 경로를 붙인다.
|
||||||
- 의존 대상 프로젝트만 있고 Milestone이 생략되면 같은 workspace의 해당 프로젝트 `current.md` 활성 Milestone을 `rely-on.target` 후보로 삼는다. 후보가 없거나 둘 이상이면 locks.yaml을 만들지 말고 사용자에게 대상 Milestone 선택을 요청한다.
|
- `locked`는 잠긴 Milestone, `rely-on.target`은 선행 조건 Milestone이다. 둘 다 같은 workspace의 어느 활성 Phase 하위 Milestone이어도 된다. 의존 대상이 `current.md`에 있어야 한다고 가정하지 않는다.
|
||||||
- 외부 의존 잠금을 만들 때 대상 Milestone의 `구현 잠금`은 `잠금`으로 두고, `rely-on.status` 기본값은 `disable`이다.
|
- "현재 마일스톤은 X 프로젝트 작업 뒤에 진행", "X 프로젝트 때문에 현재 작업 잠금", "의존성 설정해"처럼 잠긴 Milestone을 생략한 외부 의존 잠금 요청은 현재 프로젝트 `current.md`의 활성 Milestone 단일 후보를 잠긴 대상으로 삼는다.
|
||||||
- `locks.yaml`이 있고 `update-roadmap`이 갱신한 Milestone이 `[검토중]` 또는 `[완료]`가 되면 `<현재-project>:<갱신-milestone-path>`와 일치하는 `rely-on.target`의 `status`만 `enable`로 바꾼다.
|
- 의존 대상은 명시 경로, 명시 slug, 명시 제목, 잠긴 Milestone 문서의 선행 Milestone 힌트, 대상 프로젝트 `current.md` 단일 후보 순서로 확정한다.
|
||||||
- 잠금 해제 조건 충족 여부만 확인할 때는 `agent-ops/skills/common/check-roadmap-dependency/SKILL.md`를 읽고 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>"`를 사용한다. checker는 `locked`, `rely-on.target`, `rely-on.status` 필수 필드를 검증한 뒤 모든 `status`가 `enable`일 때만 `true`를 반환한다.
|
- 정규화 비교는 소문자 변환, backtick/따옴표 제거, 영문/숫자가 아닌 연속 문자를 `-` 하나로 치환, 앞뒤 `-` 제거 후 Milestone 파일 slug와 정규화한 제목에 대조한다.
|
||||||
|
- 의존 대상 탐색은 대상 프로젝트의 `agent-ops/roadmap/phase/*/milestones/*.md` 활성 문서만 대상으로 한다. archive 문서는 사용자가 archive 경로를 명시한 경우 외에는 읽거나 후보로 삼지 않는다.
|
||||||
|
- 후보가 없거나 둘 이상이면 locks.yaml을 만들거나 고치지 말고 사용자에게 대상 Milestone 선택을 요청한다.
|
||||||
|
- 외부 의존 잠금을 만들 때 대상 Milestone의 `구현 잠금`은 `잠금`으로 둔다.
|
||||||
|
- 새 `rely-on.status`는 선행 Milestone 상태에서 파생한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태거나 상태를 확인할 수 없으면 `disable`이다.
|
||||||
|
- 같은 `id` entry를 upsert할 때 기존 `rely-on` 항목을 삭제하지 않는다. 같은 `rely-on.target`만 status/note를 갱신하고, 없는 target은 추가하며, `locked` 경로가 바뀐 경우에만 `locked`를 갱신한다.
|
||||||
|
- `update-roadmap`이 갱신한 Milestone identity가 어느 entry의 `rely-on.target`과 일치하면 Milestone 상태 기준으로 `status`를 동기화한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태면 `disable`이다.
|
||||||
|
- `update-roadmap`이 갱신하거나 선택한 Milestone identity가 어느 entry의 `locked`와 일치하면 모든 `rely-on.status`가 `enable`인지 결과 보고에 남긴다. 모든 조건이 충족되어도 잠금 해제 실행은 런타임이 별도 `update-roadmap` 호출로 처리한다.
|
||||||
|
- 잠금 해제 조건 충족 여부만 확인할 때는 `agent-ops/skills/common/check-roadmap-dependency/SKILL.md`를 읽는다. lock id가 없으면 해당 스킬은 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" "<direction>" "<locks-file>"`로 현재 Milestone이 `locked`인지 `rely-on.target`인지 양방향으로 찾은 뒤 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>" "<locks-file>"`를 사용한다.
|
||||||
- checker exit code는 `0=true`, `1=false`, `2=설정/입력/파싱 오류`로 해석한다.
|
- checker exit code는 `0=true`, `1=false`, `2=설정/입력/파싱 오류`로 해석한다.
|
||||||
- 모든 `rely-on.status`가 `enable`이어도 잠금 해제 실행은 런타임이 별도 `update-roadmap` 호출로 처리한다.
|
|
||||||
|
|
||||||
## Epic과 Task id
|
## Epic과 Task id
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
# 프로젝트 간 잠금
|
# 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
- 프로젝트 상위 폴더에 `.agent-roadmap-sync/locks.yaml`이 있으면 프로젝트 간 Milestone 잠금 인덱스로 본다.
|
||||||
|
- 외부 의존 잠금 생성/동기화 요청은 `.agent-roadmap-sync/locks.yaml`이 없어도 `update-roadmap`이 생성한다.
|
||||||
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
- "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"는 `update-roadmap`으로 처리한다.
|
||||||
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
- `plan`과 `code-review`는 `.agent-roadmap-sync`를 읽거나 갱신하지 않는다.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
name: check-roadmap-dependency
|
name: check-roadmap-dependency
|
||||||
version: 1.0.0
|
version: 1.2.0
|
||||||
description: roadmap dependency lock 상태를 확인한다. 사용자가 roadmap-dependency-checker.sh, locks.yaml, 외부 의존 잠금 충족 여부, unlock-ready 판별, 프로젝트 간 잠금 해제 조건 확인을 요청할 때 사용한다.
|
description: roadmap dependency lock 상태를 확인한다. 사용자가 roadmap-dependency-checker.sh, locks.yaml, 외부 의존 잠금 충족 여부, unlock-ready 판별, 프로젝트 간 잠금 해제 조건 확인을 요청할 때 사용하며, 현재 Milestone이 locked 쪽인지 rely-on.target 쪽인지 양방향으로 판별한다.
|
||||||
---
|
---
|
||||||
|
|
||||||
# check-roadmap-dependency
|
# check-roadmap-dependency
|
||||||
|
|
@ -9,47 +9,64 @@ description: roadmap dependency lock 상태를 확인한다. 사용자가 roadma
|
||||||
## 목적
|
## 목적
|
||||||
|
|
||||||
`.agent-roadmap-sync/locks.yaml`에서 특정 lock `id`의 `locked`, `rely-on.target`, `rely-on.status`가 유효한지 확인하고, 모든 `rely-on.status`가 `enable`인지 판별한다.
|
`.agent-roadmap-sync/locks.yaml`에서 특정 lock `id`의 `locked`, `rely-on.target`, `rely-on.status`가 유효한지 확인하고, 모든 `rely-on.status`가 `enable`인지 판별한다.
|
||||||
판별은 `agent-ops/bin/roadmap-dependency-checker.sh`에 맡기고, 스킬은 입력 확정, 실행, 결과 해석만 담당한다.
|
lock id가 없으면 현재 Milestone identity가 `locked`에 있는지, `rely-on.target`에 있는지 모두 찾아 양방향으로 보고한다.
|
||||||
|
Milestone identity 역검색과 개별 lock 판별은 `agent-ops/bin/roadmap-dependency-checker.sh`에 맡기고, 스킬은 입력 확정, 실행, 결과 해석만 담당한다.
|
||||||
|
|
||||||
## 언제 호출할지
|
## 언제 호출할지
|
||||||
|
|
||||||
- 사용자가 특정 roadmap lock id의 의존 조건 충족 여부를 확인할 때
|
- 사용자가 특정 roadmap lock id의 의존 조건 충족 여부를 확인할 때
|
||||||
- runtime에서 unlock-ready 트리거 전 `locks.yaml` 판별 절차를 확인할 때
|
- runtime에서 unlock-ready 트리거 전 `locks.yaml` 판별 절차를 확인할 때
|
||||||
- `.agent-roadmap-sync/locks.yaml`의 `rely-on.status` 기반 true/false 확인을 요청할 때
|
- `.agent-roadmap-sync/locks.yaml`의 `rely-on.status` 기반 true/false 확인을 요청할 때
|
||||||
|
- 사용자가 현재 Milestone이 다른 Milestone을 잠그는지 또는 다른 Milestone에 의해 잠겼는지 확인할 때
|
||||||
|
|
||||||
## 입력
|
## 입력
|
||||||
|
|
||||||
- `lock-id`: 확인할 lock entry id. 예: `oto:oto-agent-registration`. 사용자가 "현재 마일스톤"이라고만 말하면 `<현재-project>:<current.md 활성 milestone slug>`로 추론한다. `<현재-project>`는 현재 프로젝트 루트 디렉터리 이름이다 (선택, 추론 불가 시 필수)
|
- `lock-id`: 확인할 lock entry id. 예: `oto:oto-agent-registration`. 명시되면 이 id만 판별한다 (선택)
|
||||||
|
- `target-milestone`: 확인할 Milestone path 또는 `<project>:agent-ops/roadmap/phase/.../milestones/<slug>.md`. 없으면 현재 프로젝트 `current.md`의 활성 Milestone 단일 후보를 사용한다 (선택)
|
||||||
|
- `direction`: `locked` / `rely-on` / `both`. 기본값은 `both`다. `locked`는 대상 Milestone이 잠긴 entry만, `rely-on`은 대상 Milestone을 선행 조건으로 삼는 entry만 확인한다 (선택)
|
||||||
- `locks-file`: 기본값은 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`이며, 다른 파일을 검사할 때만 지정한다 (선택)
|
- `locks-file`: 기본값은 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`이며, 다른 파일을 검사할 때만 지정한다 (선택)
|
||||||
|
|
||||||
## 먼저 확인할 것
|
## 먼저 확인할 것
|
||||||
|
|
||||||
- [ ] `agent-ops/bin/roadmap-dependency-checker.sh`가 있는지 확인한다.
|
- [ ] `agent-ops/bin/roadmap-dependency-checker.sh`가 있는지 확인한다.
|
||||||
- [ ] `lock-id`가 명시되었거나 현재 프로젝트 `current.md`의 활성 Milestone 하나로 추론 가능한지 확인한다.
|
- [ ] `lock-id`가 명시되었거나 `target-milestone` 또는 현재 프로젝트 `current.md`의 활성 Milestone 하나로 Milestone identity를 추론 가능한지 확인한다.
|
||||||
- [ ] 기본 경로 또는 지정된 `locks-file`을 읽을 수 있는지 확인한다.
|
- [ ] 기본 경로 또는 지정된 `locks-file`을 읽을 수 있는지 확인한다.
|
||||||
|
|
||||||
## 실행 절차
|
## 실행 절차
|
||||||
|
|
||||||
1. **입력 확정**
|
1. **입력 확정**
|
||||||
- 사용자 요청에서 `lock-id`를 추출한다.
|
- 사용자 요청에서 `lock-id`를 추출한다.
|
||||||
- `lock-id`가 없고 "현재 마일스톤" 확인 요청이면 현재 프로젝트 `agent-ops/roadmap/current.md`의 활성 Milestone 경로에서 milestone slug를 추출해 `<현재-project>:<milestone-slug>`를 만든다.
|
|
||||||
- 활성 Milestone 후보가 없거나 둘 이상이면 추정하지 말고 사용자에게 lock id 또는 Milestone 선택을 요청한다.
|
|
||||||
- `locks-file`이 명시되지 않았으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 사용한다.
|
- `locks-file`이 명시되지 않았으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 사용한다.
|
||||||
|
- `locks-file`이 없거나 읽을 수 없으면 결과를 `error`로 보고한다. 이를 미충족 의존성으로 해석하지 않는다.
|
||||||
|
- `lock-id`가 있으면 그 id만 판별한다.
|
||||||
|
- `lock-id`가 없으면 `target-milestone` 또는 현재 프로젝트 `agent-ops/roadmap/current.md`의 활성 Milestone 단일 후보로 Milestone identity를 만든다.
|
||||||
|
- Milestone identity는 `<project>:agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식이다.
|
||||||
|
- `target-milestone`이 `agent-ops/roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다.
|
||||||
|
- `target-milestone`이 workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-ops/roadmap/...` 경로를 붙인다.
|
||||||
|
- `target-milestone`이 archive 경로이면 일반 의존 판별 후보로 쓰지 말고 사용자에게 활성 Milestone 선택을 요청한다.
|
||||||
|
- 활성 Milestone 후보가 없거나 둘 이상이면 추정하지 말고 사용자에게 lock id 또는 Milestone 선택을 요청한다.
|
||||||
|
- `lock-id`가 없으면 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" "<direction>" "<locks-file>"`로 Milestone identity와 일치하는 entry를 찾는다.
|
||||||
|
- find 출력의 `locked:<id>`는 locked entries로, `rely-on:<id>`는 rely-on entries로 분류한다.
|
||||||
|
- find 출력이 `none`이면 결과를 `error`가 아니라 `no-lock`으로 보고한다.
|
||||||
|
|
||||||
2. **판별 실행**
|
2. **판별 실행**
|
||||||
- 기본 파일이면 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>"`를 실행한다.
|
- 확인 대상 lock id마다 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>" "<locks-file>"`를 실행한다.
|
||||||
- 지정 파일이면 `agent-ops/bin/roadmap-dependency-checker.sh "<lock-id>" "<locks-file>"`를 실행한다.
|
- `locked` 방향의 결과는 대상 Milestone의 잠금 해제 조건 충족 여부다.
|
||||||
|
- `rely-on` 방향의 결과는 대상 Milestone이 완료될 때 영향을 받는 downstream lock의 현재 충족 여부다.
|
||||||
|
|
||||||
3. **결과 해석**
|
3. **결과 해석**
|
||||||
- stdout `true`와 exit code `0`은 모든 의존 조건 충족으로 보고한다.
|
- stdout `true`와 exit code `0`은 모든 의존 조건 충족으로 보고한다.
|
||||||
- stdout `false`와 exit code `1`은 아직 충족되지 않은 의존 조건이 있음을 보고한다.
|
- stdout `false`와 exit code `1`은 아직 충족되지 않은 의존 조건이 있음을 보고한다.
|
||||||
- exit code `2`는 설정 오류, 입력 오류, 필수 필드 누락, 파싱 오류로 보고한다.
|
- exit code `2`는 설정 오류, 입력 오류, 필수 필드 누락, 파싱 오류로 보고한다.
|
||||||
|
- `rely-on` 방향에서 대상 Milestone이 `[검토중]` 또는 `[완료]`인데 status가 `disable`이면 `update-roadmap` 동기화가 필요한 stale lock으로 보고한다. 이 스킬은 status를 바꾸지 않는다.
|
||||||
|
|
||||||
## 실행 결과 검증
|
## 실행 결과 검증
|
||||||
|
|
||||||
- [ ] 정상 판별 결과가 stdout에서 `true` 또는 `false` 하나로만 출력되었는가
|
- [ ] 각 checker 실행의 stdout이 `true` 또는 `false` 하나로만 출력되었는가
|
||||||
- [ ] exit code `0`, `1`, `2` 의미를 구분해 보고했는가
|
- [ ] exit code `0`, `1`, `2` 의미를 구분해 보고했는가
|
||||||
- [ ] exit code `2`를 unlock 대기 상태로 해석하지 않았는가
|
- [ ] exit code `2`를 unlock 대기 상태로 해석하지 않았는가
|
||||||
|
- [ ] lock id가 없을 때 대상 Milestone을 `locked`와 `rely-on.target` 양쪽에서 찾았는가
|
||||||
|
- [ ] `locks.yaml`이 없는 경우 `false`가 아니라 `error`로 보고했는가
|
||||||
- [ ] 이 스킬이 `locks.yaml`이나 roadmap 문서를 수정하지 않았는가
|
- [ ] 이 스킬이 `locks.yaml`이나 roadmap 문서를 수정하지 않았는가
|
||||||
- 검증 실패 시: 오류 메시지와 사용한 `lock-id`, `locks-file` 경로를 보고하고 멈춘다.
|
- 검증 실패 시: 오류 메시지와 사용한 `lock-id`, `locks-file` 경로를 보고하고 멈춘다.
|
||||||
|
|
||||||
|
|
@ -58,10 +75,13 @@ description: roadmap dependency lock 상태를 확인한다. 사용자가 roadma
|
||||||
```markdown
|
```markdown
|
||||||
## 의존성 판별 결과
|
## 의존성 판별 결과
|
||||||
|
|
||||||
- lock-id: `<lock-id>`
|
- target-milestone: `<identity | 해당 없음>`
|
||||||
|
- direction: `<locked | rely-on | both>`
|
||||||
- locks-file: `<locks-file>`
|
- locks-file: `<locks-file>`
|
||||||
- 결과: `<true | false | error>`
|
- 결과: `<true | false | error | no-lock>`
|
||||||
- 의미: <모든 의존 조건 충족 | 미충족 의존 조건 있음 | 설정/입력/필수 필드/파싱 오류>
|
- locked entries: `<lock-id=result, ... | 없음>`
|
||||||
|
- rely-on entries: `<lock-id=result, ... | 없음>`
|
||||||
|
- 의미: <모든 의존 조건 충족 | 미충족 의존 조건 있음 | 설정/입력/필수 필드/파싱 오류 | 대상 Milestone 관련 lock 없음>
|
||||||
```
|
```
|
||||||
|
|
||||||
## 금지 사항
|
## 금지 사항
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
name: create-roadmap
|
name: create-roadmap
|
||||||
version: 1.14.0
|
version: 1.15.0
|
||||||
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase scaffold, Phase 하위 Milestone 문서, current.md 활성 Phase/Milestone 창, archive Phase scaffold를 처음 생성하는 공통 스킬
|
description: AI-first 개인/소규모 프로젝트의 전체 목표, Phase scaffold, Phase 하위 Milestone 문서, current.md 활성 Phase/Milestone 창, archive Phase scaffold를 처음 생성하는 공통 스킬
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ agent-ops/
|
||||||
- 새 `[스케치]` Milestone은 `구현 잠금`을 `잠금`으로 둔다.
|
- 새 `[스케치]` Milestone은 `구현 잠금`을 `잠금`으로 둔다.
|
||||||
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
- Milestone 전체에서 사용자만 결정할 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
|
||||||
- `구현 잠금`에는 상태와 `결정 필요` 체크리스트만 적는다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적는다.
|
- `구현 잠금`에는 상태와 `결정 필요` 체크리스트만 적는다. 결정할 항목이 없으면 `결정 필요: 없음`으로 적는다.
|
||||||
- 새 Milestone이 다른 프로젝트 Milestone 완료 전까지 잠겨야 하면 `구현 잠금`을 `잠금`으로 두고 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 entry를 만든다.
|
- 새 Milestone이 다른 프로젝트 Milestone 완료 전까지 잠겨야 하면 `구현 잠금`을 `잠금`으로 두고 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 entry를 만든다. 의존 대상 확정과 entry 형식은 `update-roadmap`의 프로젝트 간 잠금 규칙을 따른다.
|
||||||
- `기능`은 Epic heading과 Task 체크리스트로 작성한다.
|
- `기능`은 Epic heading과 Task 체크리스트로 작성한다.
|
||||||
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
|
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
|
||||||
- Task는 `- [ ] [item-id] 설명` 형식으로 작성한다.
|
- Task는 `- [ ] [item-id] 설명` 형식으로 작성한다.
|
||||||
|
|
@ -129,7 +129,7 @@ agent-ops/
|
||||||
- 완료된 Phase가 초기 구조에 포함되어야 하는 경우 `archive/phase/<phase-slug>/PHASE.md`로 만들고 `ROADMAP.md`에서 archive 경로를 가리킨다.
|
- 완료된 Phase가 초기 구조에 포함되어야 하는 경우 `archive/phase/<phase-slug>/PHASE.md`로 만들고 `ROADMAP.md`에서 archive 경로를 가리킨다.
|
||||||
- 완료된 Milestone이 진행중 Phase에 포함되어야 하는 경우 `archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 만들고 해당 활성 `PHASE.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/`만 둘 수 있다.
|
- archive `PHASE.md`는 Phase 자체가 완료/폐기된 경우에만 만든다. 진행중 Phase의 완료 Milestone만 archive된 경우 archive Phase 디렉터리에 `milestones/`만 둘 수 있다.
|
||||||
- 외부 의존 잠금이 있으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 생성하거나 기존 entry를 upsert한다.
|
- 외부 의존 잠금이 있으면 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`을 생성하거나 기존 entry를 upsert한다. 의존 대상이 명시 경로, slug, 제목, 문서 힌트, current 단일 후보 중 하나로 확정되지 않으면 lock entry를 만들지 않고 TODO로 남긴다.
|
||||||
|
|
||||||
5. **검증**
|
5. **검증**
|
||||||
- 생성한 링크가 실제 파일을 가리키는지 확인한다.
|
- 생성한 링크가 실제 파일을 가리키는지 확인한다.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
name: update-roadmap
|
name: update-roadmap
|
||||||
version: 1.19.0
|
version: 1.20.0
|
||||||
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가/갱신, phase/페이즈 변경 요청에 사용한다. Roadmap-Phase-Milestone scaffold에서 target 없는 신규 작업의 규모를 판정하고 기존 Phase/Milestone/Epic/Task를 검색해 upsert한 뒤, 없을 때만 새 항목을 만들고 current.md 동기화, runtime m-task 완료 이벤트 반영, 완료 후보 검토중 전환, 승인된 archive 이동을 처리한다.
|
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가/갱신, phase/페이즈 변경 요청에 사용한다. Roadmap-Phase-Milestone scaffold에서 target 없는 신규 작업의 규모를 판정하고 기존 Phase/Milestone/Epic/Task를 검색해 upsert한 뒤, 없을 때만 새 항목을 만들고 current.md 동기화, runtime m-task 완료 이벤트 반영, 완료 후보 검토중 전환, 승인된 archive 이동, workspace 외부 의존 잠금 양방향 동기화를 처리한다.
|
||||||
---
|
---
|
||||||
|
|
||||||
# 로드맵 업데이트
|
# 로드맵 업데이트
|
||||||
|
|
@ -47,7 +47,7 @@ Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능
|
||||||
- `review-comment`: 완료 리뷰에 남길 사용자 확인, 보완, 보류, 폐기 방향성 (선택)
|
- `review-comment`: 완료 리뷰에 남길 사용자 확인, 보완, 보류, 폐기 방향성 (선택)
|
||||||
- `origin-task`: 런타임 완료 이벤트가 전달한 `agent-task/m-<milestone-slug>` 또는 `agent-task/m-<milestone-slug>/<subtask_dir>` 형식의 원래 active task 경로. 이벤트가 최종 archive 경로만 갖고 있으면 런타임이 이 형식으로 정규화해 전달한다 (선택)
|
- `origin-task`: 런타임 완료 이벤트가 전달한 `agent-task/m-<milestone-slug>` 또는 `agent-task/m-<milestone-slug>/<subtask_dir>` 형식의 원래 active task 경로. 이벤트가 최종 archive 경로만 갖고 있으면 런타임이 이 형식으로 정규화해 전달한다 (선택)
|
||||||
- `archive-date`: Phase/Milestone 아카이브 날짜. 없으면 현재 날짜를 사용한다 (선택)
|
- `archive-date`: Phase/Milestone 아카이브 날짜. 없으면 현재 날짜를 사용한다 (선택)
|
||||||
- `workspace-lock`: 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 기록할 외부 의존 잠금 설명 (선택)
|
- `workspace-lock`: 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 기록하거나 동기화할 외부 의존 잠금 설명 (선택)
|
||||||
|
|
||||||
## 표준 구조
|
## 표준 구조
|
||||||
|
|
||||||
|
|
@ -123,16 +123,28 @@ agent-ops/roadmap/
|
||||||
|
|
||||||
## 프로젝트 간 잠금
|
## 프로젝트 간 잠금
|
||||||
|
|
||||||
- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다.
|
- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다. 외부 의존 잠금을 생성하거나 동기화해야 하면 파일이 없어도 디렉터리와 파일을 만든다.
|
||||||
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
|
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
|
||||||
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
|
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
|
||||||
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
|
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
|
||||||
- `locked`와 `rely-on[].target`은 `<project>:agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
|
- `locked`와 `rely-on[].target`은 `<project>:agent-ops/roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
|
||||||
- "현재 마일스톤은 X 프로젝트 작업 뒤에 진행", "X 프로젝트 때문에 현재 작업 잠금", "의존성 설정해"처럼 대상 Milestone이 생략된 외부 의존 잠금 요청은 현재 프로젝트의 `current.md` 활성 Milestone을 잠긴 대상으로 삼는다.
|
- Milestone 경로가 `agent-ops/roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다. workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-ops/roadmap/...` 경로를 붙인다.
|
||||||
- 의존 대상 프로젝트명만 있고 Milestone이 생략되면 같은 workspace의 해당 프로젝트 `agent-ops/roadmap/current.md` 활성 Milestone을 `rely-on.target` 후보로 삼는다.
|
- `locked`는 잠긴 Milestone, `rely-on.target`은 선행 조건 Milestone이다. 둘 다 같은 workspace의 어느 활성 Phase 하위 Milestone이어도 된다. 의존 대상이 `current.md`에 있어야 한다고 가정하지 않는다.
|
||||||
- 의존 대상 프로젝트가 없거나, 해당 프로젝트의 활성 Milestone 후보가 없거나 둘 이상이면 `locks.yaml`을 만들지 말고 사용자에게 대상 프로젝트/Milestone 선택을 요청한다.
|
- 의존 Milestone 확정 순서:
|
||||||
- 외부 의존 잠금 요청은 대상 Milestone의 `구현 잠금`을 `잠금`으로 두고, `locked`, `rely-on.target`, `rely-on.status=disable`로 upsert한다.
|
1. 사용자가 명시한 `<project>:agent-ops/roadmap/phase/.../milestones/<slug>.md` 또는 파일 경로
|
||||||
- `locks.yaml`이 있고 이 스킬이 갱신한 Milestone이 `[검토중]` 또는 `[완료]`가 되면 `<현재-project>:<갱신-milestone-path>`와 일치하는 `rely-on.target`의 `status`만 `enable`로 바꾼다.
|
2. 사용자가 명시한 프로젝트와 Milestone slug
|
||||||
|
3. 사용자가 명시한 프로젝트와 Milestone 제목의 정규화 일치
|
||||||
|
4. 잠긴 Milestone 문서의 `선행 <project> Milestone: ...`, `관련 <project> Milestone: ...`, `외부 의존 잠금: ...`에 적힌 slug/제목 힌트
|
||||||
|
5. 프로젝트명만 있고 Milestone 힌트가 없을 때만 해당 프로젝트 `current.md`의 활성 Milestone 단일 후보
|
||||||
|
- 정규화 비교는 소문자 변환, backtick/따옴표 제거, 영문/숫자가 아닌 연속 문자를 `-` 하나로 치환, 앞뒤 `-` 제거 후 비교한다. 정규화한 힌트는 Milestone 파일 slug와 정규화한 제목 둘 다에 대조한다.
|
||||||
|
- 2-4번 탐색은 대상 프로젝트의 `agent-ops/roadmap/phase/*/milestones/*.md` 활성 문서만 대상으로 한다. archive 문서는 사용자가 archive 경로를 명시한 경우 외에는 읽거나 후보로 삼지 않는다.
|
||||||
|
- 후보가 없거나 둘 이상이면 `locks.yaml`을 만들거나 고치지 말고 사용자에게 대상 Milestone 선택을 요청한다.
|
||||||
|
- 외부 의존 잠금 요청이 있거나, 갱신 대상 Milestone이 `구현 잠금: 잠금`이며 문서에 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 `.agent-roadmap-sync/locks.yaml`을 upsert한다. resolvable한 외부 의존 문구를 Milestone에 남기고 lock entry를 누락하지 않는다.
|
||||||
|
- 외부 의존 잠금을 만들 때 대상 Milestone의 `구현 잠금`은 `잠금`으로 둔다.
|
||||||
|
- 새 `rely-on.status`는 선행 Milestone 상태에서 파생한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태거나 상태를 확인할 수 없으면 `disable`이다.
|
||||||
|
- 같은 `id` entry를 upsert할 때 기존 `rely-on` 항목을 삭제하지 않는다. 같은 `rely-on.target`만 status/note를 갱신하고, 없는 target은 추가하며, `locked` 경로가 바뀐 경우에만 `locked`를 갱신한다.
|
||||||
|
- 이 스킬이 갱신한 Milestone identity가 어느 entry의 `rely-on.target`과 일치하면 해당 `rely-on.status`를 Milestone 상태 기준으로 동기화한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태면 `disable`이다.
|
||||||
|
- 이 스킬이 갱신하거나 선택한 Milestone identity가 어느 entry의 `locked`와 일치하면 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고의 `Workspace 잠금`에 `런타임 해제 대기` 또는 `미충족`으로 남긴다.
|
||||||
- 모든 `rely-on.status`가 `enable`이어도 여기서 다른 프로젝트 Milestone을 직접 해제하지 않는다. 잠금 해제 실행은 런타임이 별도 `update-roadmap` 호출로 처리한다.
|
- 모든 `rely-on.status`가 `enable`이어도 여기서 다른 프로젝트 Milestone을 직접 해제하지 않는다. 잠금 해제 실행은 런타임이 별도 `update-roadmap` 호출로 처리한다.
|
||||||
|
|
||||||
## 완료 리뷰와 검토중 상태
|
## 완료 리뷰와 검토중 상태
|
||||||
|
|
@ -246,9 +258,10 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
||||||
- 새 기능 배치, Epic/Task 추가는 `milestone` 또는 `phase`로 본다.
|
- 새 기능 배치, Epic/Task 추가는 `milestone` 또는 `phase`로 본다.
|
||||||
- "로드맵에 추가"처럼 target이 없는 신규 작업 요청은 `placement=auto`, `placement-unit=auto`, `new-feature=<요청 내용>`으로 본다.
|
- "로드맵에 추가"처럼 target이 없는 신규 작업 요청은 `placement=auto`, `placement-unit=auto`, `new-feature=<요청 내용>`으로 본다.
|
||||||
- 외부 의존 잠금 요청이면 `workspace-lock` 갱신으로 본다.
|
- 외부 의존 잠금 요청이면 `workspace-lock` 갱신으로 본다.
|
||||||
- 외부 의존 잠금 요청에서 "현재 마일스톤" 또는 target 생략 표현이 있으면 `current.md`의 활성 Milestone을 잠긴 대상으로 확정한다.
|
- 외부 의존 잠금 요청이 아니어도, 갱신 대상 Milestone이 `구현 잠금: 잠금`이고 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 `workspace-lock` 동기화 후보로 본다.
|
||||||
- 외부 의존 잠금 요청에서 의존 프로젝트명만 있으면 같은 workspace의 `<project>/agent-ops/roadmap/current.md`를 읽고 활성 Milestone을 의존 대상으로 확정한다.
|
- 외부 의존 잠금 요청에서 "현재 마일스톤" 또는 target 생략 표현이 있으면 `current.md`의 활성 Milestone 단일 후보를 잠긴 대상으로 확정한다.
|
||||||
- 잠긴 대상 또는 의존 대상 활성 Milestone 후보가 없거나 둘 이상이면 `locks.yaml`을 수정하지 말고 사용자에게 Milestone 선택을 요청한다.
|
- 의존 대상은 명시 경로, 명시 slug, 명시 제목, 잠긴 Milestone 문서의 선행 Milestone 힌트, 대상 프로젝트 `current.md` 단일 후보 순서로 확정한다.
|
||||||
|
- 잠긴 대상 또는 의존 대상 후보가 없거나 둘 이상이면 `locks.yaml`을 수정하지 말고 사용자에게 Milestone 선택을 요청한다.
|
||||||
|
|
||||||
2. **요청 정규화와 규모 판정**
|
2. **요청 정규화와 규모 판정**
|
||||||
- 요청에서 기능명, 목표, 관련 경로, 명시 anchor, 완료 기대, 제약을 추출한다.
|
- 요청에서 기능명, 목표, 관련 경로, 명시 anchor, 완료 기대, 제약을 추출한다.
|
||||||
|
|
@ -287,9 +300,12 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
||||||
- 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이면 Milestone 상태를 `[검토중]`으로 바꾸고 `완료 리뷰`에 리뷰 요청과 근거를 남긴다.
|
- 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이면 Milestone 상태를 `[검토중]`으로 바꾸고 `완료 리뷰`에 리뷰 요청과 근거를 남긴다.
|
||||||
- `[검토중]` 전환만으로 archive 이동, `current.md` 제거, archive 링크 변경을 수행하지 않는다.
|
- `[검토중]` 전환만으로 archive 이동, `current.md` 제거, archive 링크 변경을 수행하지 않는다.
|
||||||
- 사용자 승인 근거가 있으면 `[검토중]`을 `[완료]`로 전환하고 archive 모드를 수행할 수 있다.
|
- 사용자 승인 근거가 있으면 `[검토중]`을 `[완료]`로 전환하고 archive 모드를 수행할 수 있다.
|
||||||
- 외부 의존 잠금 요청이면 대상 Milestone의 `구현 잠금`을 `잠금`으로 두고 `.agent-roadmap-sync/locks.yaml`을 upsert한다.
|
- 외부 의존 잠금 요청 또는 외부 의존 컨텍스트 동기화가 필요하면 대상 Milestone의 `구현 잠금`을 `잠금`으로 두고 `.agent-roadmap-sync/locks.yaml`을 upsert한다.
|
||||||
- `locks.yaml` entry는 `id=<잠긴-project>:<잠긴-milestone-slug>`, `locked=<잠긴-project>:<잠긴-milestone-path>`, `rely-on.target=<의존-project>:<의존-milestone-path>`, `rely-on.status=disable`, `rely-on.note=<사용자 요청 요약>`으로 기록한다.
|
- `.agent-roadmap-sync/locks.yaml`이 없으면 `.agent-roadmap-sync/` 디렉터리와 `locks.yaml` 파일을 만든다.
|
||||||
- `locks.yaml`이 있고 갱신한 Milestone이 `[검토중]` 또는 `[완료]`가 되었으면 `<현재-project>:<갱신-milestone-path>`와 일치하는 `rely-on.target`을 `enable`로 바꾼다.
|
- `locks.yaml` entry는 `id=<잠긴-project>:<잠긴-milestone-slug>`, `locked=<잠긴-project>:<잠긴-milestone-path>`, `rely-on.target=<의존-project>:<의존-milestone-path>`, `rely-on.status=<enable|disable>`, `rely-on.note=<사용자 요청 요약>`으로 기록한다.
|
||||||
|
- 같은 `id` entry가 있으면 기존 `rely-on` 목록을 보존하고 같은 `target`만 갱신하거나 새 `target`을 추가한다.
|
||||||
|
- 갱신한 Milestone identity와 일치하는 `rely-on.target`은 Milestone 상태 기준으로 `enable` 또는 `disable`을 동기화한다.
|
||||||
|
- 갱신하거나 선택한 Milestone identity와 일치하는 `locked` entry가 있으면 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고에 남긴다.
|
||||||
|
|
||||||
6. **검증**
|
6. **검증**
|
||||||
- `current.md`의 활성 Phase/Milestone 경로가 실제 파일을 가리키는지 확인한다.
|
- `current.md`의 활성 Phase/Milestone 경로가 실제 파일을 가리키는지 확인한다.
|
||||||
|
|
@ -308,6 +324,8 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
||||||
- 동일/유사 기존 항목을 검색했고 신규/업데이트 판정이 결과 보고에 남았는지 확인한다.
|
- 동일/유사 기존 항목을 검색했고 신규/업데이트 판정이 결과 보고에 남았는지 확인한다.
|
||||||
- 자동 배치한 신규 작업이면 선택한 후보와 밀린 후보의 근거가 결과 보고에 포함되는지 확인한다.
|
- 자동 배치한 신규 작업이면 선택한 후보와 밀린 후보의 근거가 결과 보고에 포함되는지 확인한다.
|
||||||
- `.agent-roadmap-sync/locks.yaml`을 갱신했다면 `locked`, `rely-on.target`, `rely-on.status`가 채워졌는지 확인한다.
|
- `.agent-roadmap-sync/locks.yaml`을 갱신했다면 `locked`, `rely-on.target`, `rely-on.status`가 채워졌는지 확인한다.
|
||||||
|
- 갱신 대상 Milestone에 resolvable한 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 해당 lock entry가 존재하는지 확인한다.
|
||||||
|
- 갱신 대상 Milestone identity가 `locked` 또는 `rely-on.target` 어느 쪽에 있든 결과 보고의 `Workspace 잠금`에 반영했는지 확인한다.
|
||||||
- `git diff --check`로 공백 오류를 확인한다.
|
- `git diff --check`로 공백 오류를 확인한다.
|
||||||
|
|
||||||
7. **결과 보고**
|
7. **결과 보고**
|
||||||
|
|
@ -352,7 +370,7 @@ target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다
|
||||||
- 승격 조건: <해당 없음 | 추가/수정/미충족 유지/충족 요약>
|
- 승격 조건: <해당 없음 | 추가/수정/미충족 유지/충족 요약>
|
||||||
- 완료 리뷰: <변경 없음 | 요청됨 | 승인됨 | 보완 필요 | 보류 | 폐기>
|
- 완료 리뷰: <변경 없음 | 요청됨 | 승인됨 | 보완 필요 | 보류 | 폐기>
|
||||||
- runtime m-task 라우팅: <해당 없음 | origin-task -> target Milestone | target 불명확>
|
- runtime m-task 라우팅: <해당 없음 | origin-task -> target Milestone | target 불명확>
|
||||||
- Workspace 잠금: <변경 없음 | entry 생성/갱신 | rely-on enable | 런타임 해제 대기>
|
- Workspace 잠금: <변경 없음 | entry 생성/갱신 | rely-on enable | rely-on disable | 미충족 | 런타임 해제 대기>
|
||||||
- 활성 항목: <변경 없음 | Phase/Milestone 추가/제거 요약>
|
- 활성 항목: <변경 없음 | Phase/Milestone 추가/제거 요약>
|
||||||
- 아카이브: <변경 없음 | 이동 경로와 남긴 링크>
|
- 아카이브: <변경 없음 | 이동 경로와 남긴 링크>
|
||||||
- 상태: <변경 없음 | 이전 -> 이후>
|
- 상태: <변경 없음 | 이전 -> 이후>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue