Merge commit '0c7c1f7bcf7e11c2b0e1b67fdd49382b3cb86e43'

This commit is contained in:
2026-05-11 01:09:46 +00:00
24 changed files with 139 additions and 44 deletions
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/bootstrap-baseline/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/capture-release-feedback/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/change-req/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/confirm-batch-verification/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/confirm-discovery/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/confirm-release/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/confirm-req-implemented/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/confirm-req/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/draft-batch-design/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/draft-batch-planning/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/draft-batch-verification/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/draft-batch/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/draft-release/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/draft-req/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/new-discovery/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/review-discovery/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/run-batch-implementation/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/run-sdlc/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/suggest-batch-reqs/SKILL.md` exactly.
@@ -0,0 +1 @@
Follow the instructions in `.github/skills/suggest-next-discovery/SKILL.md` exactly.
+19 -44
View File
@@ -269,36 +269,21 @@ Discovery 문서의 `# 3. 문제점의 요약` 중 `현재 상태`를 채우기
1. 입력 원문이 있으면 이슈명을 한 문장으로 정리하고, 없으면 저장소 상태를 먼저 분류한다.
2. 파라미터 없는 실행이면 discovery/srs/batches/releases/baseline 문서 상태를 읽어 `no-history`, `active-cycle`, `ready-for-next-iteration` 중 하나로 판정한다.
<<<<<<< HEAD
3. 입력 원문이 없고 `active-cycle`이면 새 Discovery 자동 생성을 중단하고 현재 반복을 계속 진행해야 하는 이유와 추천 skill을 보고한다.
4. 입력 원문이 없고 `no-history`이면 baseline Discovery를 생성 대상으로 확정한다.
5. 입력 원문이 없고 `ready-for-next-iteration`이면 이전 Discovery, SRS, 구현 상태, baseline 문서 상태를 바탕으로 추천 follow-up Discovery 주제를 정한다.
6. 입력 원문, 이슈 링크, 신규 요구 요약처럼 명시적 신규 입력이 있으면 `active-cycle` 여부와 무관하게 위 `확인 절차`에 따라 issue 번호/링크, 제목 키워드, 기능명, 범위 키워드를 추출하고 기존 후보 주기를 찾는다.
7. 입력 원문이 없고 추천 Discovery 주제가 정해졌으면 위 `확인 절차`에 따라 issue 번호/링크, 제목 키워드, 기능명, 범위 키워드를 추출하고 기존 후보 주기를 찾는다.
8. 후보 비교 결과를 바탕으로 `기존 Discovery 갱신` 또는 `새 Discovery 생성`으로 판정한다.
9. `active-cycle` 상태에서 명시적 신규 입력으로 새 Discovery를 진행하는 경우, 기존 active unit와의 범위 충돌 여부와 병렬 진행 사유를 함께 기록한다.
10. 판정이 애매하면 사용자 확인 전까지 자동 생성 또는 자동 갱신을 중단하고 후보와 근거를 보고한다.
11. 저장소 현황 탐색을 수행한다.
12. 판정 결과가 `새 Discovery 생성`이면 기존 `docs/discovery/` 경로를 다시 스캔해 다음 번호를 계산한다.
13. `새 Discovery 생성`이면 날짜와 slug를 조합해 `DISCOVERY_ID`를 만든다.
14. `새 Discovery 생성`이면 `docs/discovery/<DISCOVERY_ID>.md` 파일을 생성한다.
15. `기존 Discovery 갱신`이면 대상 Discovery 문서를 갱신한다.
16. 아래 플레이스홀더를 우선 치환한다.
=======
3. `active-cycle`이면 새 Discovery 생성을 중단하고 현재 반복을 계속 진행해야 하는 이유와 추천 skill을 보고한다.
4. `no-history`이고 baseline 문서 또는 active index가 비어 있으면 `bootstrap-baseline`을 우선 추천하고 Discovery 생성을 중단한다.
5. `no-history`이지만 baseline 초기화가 끝나 있으면 첫 real Discovery 생성 대상으로 확정한다.
6. `ready-for-next-iteration`이면 이전 Discovery, SRS, 구현 상태, baseline 문서 상태를 바탕으로 추천 follow-up Discovery 주제를 정한다.
7. 입력 원문이 있거나 추천 Discovery 주제가 정해졌으면 위 `확인 절차`에 따라 issue 번호/링크, 제목 키워드, 기능명, 범위 키워드를 추출하고 기존 후보 주기를 찾는다.
8. 후보 비교 결과를 바탕으로 `기존 Discovery 갱신` 또는 `새 Discovery 생성`으로 판정한다.
9. 판정이 애매하면 사용자 확인 전까지 자동 생성 또는 자동 갱신을 중단하고 후보와 근거를 보고한다.
10. 저장소 현황 탐색을 수행한다.
11. 판정 결과가 `새 Discovery 생성`이면 기존 `docs/discovery/` 경로를 다시 스캔해 다음 번호를 계산한다.
12. `새 Discovery 생성`이면 날짜와 slug를 조합해 `DISCOVERY_ID`를 만든다.
13. `새 Discovery 생성`이면 `docs/discovery/<DISCOVERY_ID>.md` 파일을 생성한다.
14. `기존 Discovery 갱신`이면 대상 Discovery 문서를 갱신한다.
15. 아래 플레이스홀더를 우선 치환한다.
>>>>>>> e15c3d2 (feat: introduce lightweight change path, change-req skill, and release feedback loop)
6. 입력 원문이 없고 `ready-for-next-iteration`이면 이전 Discovery, SRS, 구현 상태, baseline 문서 상태를 바탕으로 추천 follow-up Discovery 주제를 정한다.
7. 입력 원문, 이슈 링크, 신규 요구 요약처럼 명시적 신규 입력이 있으면 `active-cycle` 여부와 무관하게 위 `확인 절차`에 따라 issue 번호/링크, 제목 키워드, 기능명, 범위 키워드를 추출하고 기존 후보 주기를 찾는다.
8. 입력 원문이 없고 추천 Discovery 주제가 정해졌으면 위 `확인 절차`에 따라 issue 번호/링크, 제목 키워드, 기능명, 범위 키워드를 추출하고 기존 후보 주기를 찾는다.
9. 후보 비교 결과를 바탕으로 `기존 Discovery 갱신` 또는 `새 Discovery 생성`으로 판정한다.
10. `active-cycle` 상태에서 명시적 신규 입력으로 새 Discovery를 진행하는 경우, 기존 active unit와의 범위 충돌 여부와 병렬 진행 사유를 함께 기록한다.
11. 판정이 애매하면 사용자 확인 전까지 자동 생성 또는 자동 갱신을 중단하고 후보와 근거를 보고한다.
12. 저장소 현황 탐색을 수행한다.
13. 판정 결과가 `새 Discovery 생성`이면 기존 `docs/discovery/` 경로를 다시 스캔해 다음 번호를 계산한다.
14. `새 Discovery 생성`이면 날짜와 slug를 조합해 `DISCOVERY_ID`를 만든다.
15. `새 Discovery 생성`이면 `docs/discovery/<DISCOVERY_ID>.md` 파일을 생성한다.
16. `기존 Discovery 갱신`이면 대상 Discovery 문서를 갱신한다.
17. 아래 플레이스홀더를 우선 치환한다.
- `{{DOC_STATUS:draft|review|confirmed}}` -> `draft`
- `{{DISCOVERY_ID:dcy-<3자리>_<YYYYMMDD>_<topic-slug>}}` -> 계산한 `DISCOVERY_ID`
- `{{ISSUE_NAME:짧은 한글 또는 영문 이슈명}}` -> 입력 원문 또는 요약 이슈명
@@ -311,23 +296,13 @@ Discovery 문서의 `# 3. 문제점의 요약` 중 `현재 상태`를 채우기
- `{{FOLLOW_UP_DISCOVERY_REF:없음 또는 docs/discovery/<DISCOVERY_ID>.md}}` -> `없음` 또는 후속 Discovery 경로
- `{{OUTPUT_PATH}}` -> 생성 파일 경로
- `{{FILE_RESULT:생성|갱신|미생성}}` -> `생성`
<<<<<<< HEAD
17. baseline Discovery 또는 baseline 문서 보완 Discovery면 `docs/project-structure.md`와 `docs/runtime-flows.md` 생성/갱신 요구를 핵심 변경과 FR에 반영한다.
18. `기존 Discovery 갱신`인 경우 `{{OUTPUT_PATH}}`와 `{{FILE_RESULT}}`는 갱신 대상 파일과 `갱신`으로 해석한다.
19. `새 Discovery 생성`이면서 기존 Discovery를 대체하거나 이어받는 경우, 기존 Discovery 문서에 `대체됨` 또는 `후속 주기 참조` 필드를 새 문서 경로로 갱신한다.
20. Discovery 문서에서는 추론 가능한 플레이스홀더를 적극적으로 실제 내용으로 치환한다.
21. 추론 불가능하거나 사용자 확인이 필요한 항목만 플레이스홀더로 남긴다.
22. `새 Discovery 생성`인 경우에만 `docs/discovery/index.md` 전역 인덱스에 새 행을 추가한다.
23. `기존 Discovery 갱신`인 경우 전역 인덱스에 새 행을 추가하지 않는다.
=======
16. Discovery가 구조 또는 runtime baseline 갭을 직접 다루면 `docs/project-structure.md`와 `docs/runtime-flows.md` 갱신 요구를 핵심 변경과 FR에 반영한다.
17. `기존 Discovery 갱신`인 경우 `{{OUTPUT_PATH}}`와 `{{FILE_RESULT}}`는 갱신 대상 파일과 `갱신`으로 해석한다.
18. `새 Discovery 생성`이면서 기존 Discovery를 대체하거나 이어받는 경우, 기존 Discovery 문서에 `대체됨` 또는 `후속 주기 참조` 필드를 새 문서 경로로 갱신한다.
19. Discovery 문서에서는 추론 가능한 플레이스홀더를 적극적으로 실제 내용으로 치환한다.
20. 추론 불가능하거나 사용자 확인이 필요한 항목만 플레이스홀더로 남긴다.
21. `새 Discovery 생성`인 경우에만 `docs/discovery/index.md` 전역 인덱스에 새 행을 추가한다.
22. `기존 Discovery 갱신`인 경우 전역 인덱스에 새 행을 추가하지 않는다.
>>>>>>> e15c3d2 (feat: introduce lightweight change path, change-req skill, and release feedback loop)
18. Discovery가 구조 또는 runtime baseline 갭을 직접 다루면 `docs/project-structure.md`와 `docs/runtime-flows.md` 갱신 요구를 핵심 변경과 FR에 반영한다.
19. `기존 Discovery 갱신`인 경우 `{{OUTPUT_PATH}}`와 `{{FILE_RESULT}}`는 갱신 대상 파일과 `갱신`으로 해석한다.
20. `새 Discovery 생성`이면서 기존 Discovery를 대체하거나 이어받는 경우, 기존 Discovery 문서에 `대체됨` 또는 `후속 주기 참조` 필드를 새 문서 경로로 갱신한다.
21. Discovery 문서에서는 추론 가능한 플레이스홀더를 적극적으로 실제 내용으로 치환한다.
22. 추론 불가능하거나 사용자 확인이 필요한 항목만 플레이스홀더로 남긴다.
23. `새 Discovery 생성`인 경우에만 `docs/discovery/index.md` 전역 인덱스에 새 행을 추가한다.
24. `기존 Discovery 갱신`인 경우 전역 인덱스에 새 행을 추가하지 않는다.
# Global Index Rules
+11
View File
@@ -396,6 +396,17 @@ Discovery는 구현 완료 상태를 표현하는 단위가 아니다. Discovery
- `docs/batches/index.md`
- `docs/releases/index.md`
### 12.1 새 skill 추가 시 체크리스트
skill을 새로 추가할 때는 아래 두 파일을 반드시 함께 추가한다.
| 파일 | 역할 |
| --- | --- |
| `.github/skills/<name>/SKILL.md` | Copilot용 skill 본문 |
| `.claude/commands/<name>.md` | Claude Code용 wrapper (내용: `Follow the instructions in \`.github/skills/<name>/SKILL.md\` exactly.`) |
skill을 삭제하거나 이름을 변경할 때도 두 경로를 함께 처리한다.
## 13. 빠른 점검표
### 13.1 Requirements 진입 전
@@ -26,6 +26,7 @@ ensure_host_structure() {
".github/runbooks/services"
".github/scripts"
".github/templates"
".claude/commands"
"docs/discovery"
"docs/srs"
"docs/batches"
+88
View File
@@ -68,6 +68,7 @@ done
HOST_ROOT="${ARGS[0]:-$(pwd)}"
POLICY="${ARGS[1]:-${STAGEPILOT_CONFLICT_POLICY:-preserve}}"
TARGET_GITHUB="${HOST_ROOT}/.github"
TARGET_CLAUDE="${HOST_ROOT}/CLAUDE.md"
STAGEPILOT_BEGIN="<!-- STAGEPILOT:BEGIN -->"
STAGEPILOT_END="<!-- STAGEPILOT:END -->"
@@ -177,11 +178,95 @@ merge_stagepilot_section() {
rm -f "${payload_file}" "${output_file}"
}
install_claude_section() {
local src_copilot="${SOURCE_GITHUB}/copilot-instructions.md"
[ -f "${src_copilot}" ] || { log "copilot-instructions.md not found; skipping CLAUDE.md"; return 0; }
if [ ! -e "${TARGET_CLAUDE}" ]; then
local payload_file
payload_file="$(mktemp)"
if grep -Fq "${STAGEPILOT_BEGIN}" "${src_copilot}" && grep -Fq "${STAGEPILOT_END}" "${src_copilot}"; then
awk -v begin="${STAGEPILOT_BEGIN}" -v end="${STAGEPILOT_END}" '
$0 == begin { in_block=1; next }
$0 == end { in_block=0; exit }
in_block { print }
' "${src_copilot}" > "${payload_file}"
else
cat "${src_copilot}" > "${payload_file}"
fi
if [ "${DRY_RUN}" -eq 1 ]; then
log "[dry-run] create: CLAUDE.md"
else
{
printf '%s\n' "${STAGEPILOT_BEGIN}"
cat "${payload_file}"
printf '%s\n' "${STAGEPILOT_END}"
} > "${TARGET_CLAUDE}"
fi
rm -f "${payload_file}"
else
merge_stagepilot_section "${src_copilot}" "${TARGET_CLAUDE}"
fi
}
# NOTE: skill을 추가/삭제/이름변경할 때는 .github/skills/<name>/SKILL.md와
# .claude/commands/<name>.md를 반드시 함께 처리한다. (README 12.1 참고)
install_claude_commands() {
local source_commands="${PACKAGE_ROOT}/.claude/commands"
local target_commands="${HOST_ROOT}/.claude/commands"
[ -d "${source_commands}" ] || { log "no .claude/commands source; skipping"; return 0; }
while IFS= read -r -d '' src_file; do
local cmd_name
cmd_name="$(basename "${src_file}")"
local dst_file="${target_commands}/${cmd_name}"
if [ ! -e "${dst_file}" ]; then
if [ "${DRY_RUN}" -eq 1 ]; then
log "[dry-run] create: .claude/commands/${cmd_name}"
else
mkdir -p "${target_commands}"
cp -a "${src_file}" "${dst_file}"
fi
claude_installed=$((claude_installed + 1))
continue
fi
if cmp -s "${src_file}" "${dst_file}"; then
claude_skipped=$((claude_skipped + 1))
continue
fi
case "${POLICY}" in
replace)
if [ "${DRY_RUN}" -eq 1 ]; then
log "[dry-run] replace: .claude/commands/${cmd_name}"
else
cp -a "${src_file}" "${dst_file}"
fi
claude_installed=$((claude_installed + 1))
;;
preserve)
claude_skipped=$((claude_skipped + 1))
;;
fail)
printf '[install] CONFLICT: .claude/commands/%s\n' "${cmd_name}" >&2
failed=$((failed + 1))
;;
esac
done < <(find "${source_commands}" -maxdepth 1 -name "*.md" -print0 | sort -z)
log "claude_commands: installed=${claude_installed} skipped=${claude_skipped}"
}
copied=0
skipped=0
conflicted=0
failed=0
merged=0
claude_installed=0
claude_skipped=0
mkdir -p "${TARGET_GITHUB}"
@@ -255,6 +340,9 @@ if [ "${CLEANUP_LEGACY_BASE}" -eq 1 ]; then
fi
fi
install_claude_section
install_claude_commands
log "host_root=${HOST_ROOT}"
log "source=${SOURCE_GITHUB}"
log "source_path=${SOURCE_PATH}"