From 9ed307555a3ffbdc755923e09cc1b635c4b13697 Mon Sep 17 00:00:00 2001 From: Justin Ko Date: Mon, 11 May 2026 01:18:50 +0000 Subject: [PATCH] docs: add discovery dcy-004 for portfolio ID UUID migration and user-scoped name resolution - Initialize Discovery document for portfolio UUID migration initiative - Update discovery index with new DCY-004 entry - Refactor new-discovery skill with streamlined guidance - Add CLAUDE.md and .claude/ for local StagePilot configuration --- .claude/commands/bootstrap-baseline.md | 1 + .claude/commands/capture-release-feedback.md | 1 + .claude/commands/change-req.md | 1 + .../commands/confirm-batch-verification.md | 1 + .claude/commands/confirm-discovery.md | 1 + .claude/commands/confirm-release.md | 1 + .claude/commands/confirm-req-implemented.md | 1 + .claude/commands/confirm-req.md | 1 + .claude/commands/draft-batch-design.md | 1 + .claude/commands/draft-batch-planning.md | 1 + .claude/commands/draft-batch-verification.md | 1 + .claude/commands/draft-batch.md | 1 + .claude/commands/draft-release.md | 1 + .claude/commands/draft-req.md | 1 + .claude/commands/new-discovery.md | 1 + .claude/commands/review-discovery.md | 1 + .claude/commands/run-batch-implementation.md | 1 + .claude/commands/run-sdlc.md | 1 + .claude/commands/suggest-batch-reqs.md | 1 + .claude/commands/suggest-next-discovery.md | 1 + .github/skills/new-discovery/SKILL.md | 63 ++--- CLAUDE.md | 71 ++++++ ...gration-and-user-scoped-name-resolution.md | 235 ++++++++++++++++++ docs/discovery/index.md | 3 +- 24 files changed, 347 insertions(+), 45 deletions(-) create mode 100644 .claude/commands/bootstrap-baseline.md create mode 100644 .claude/commands/capture-release-feedback.md create mode 100644 .claude/commands/change-req.md create mode 100644 .claude/commands/confirm-batch-verification.md create mode 100644 .claude/commands/confirm-discovery.md create mode 100644 .claude/commands/confirm-release.md create mode 100644 .claude/commands/confirm-req-implemented.md create mode 100644 .claude/commands/confirm-req.md create mode 100644 .claude/commands/draft-batch-design.md create mode 100644 .claude/commands/draft-batch-planning.md create mode 100644 .claude/commands/draft-batch-verification.md create mode 100644 .claude/commands/draft-batch.md create mode 100644 .claude/commands/draft-release.md create mode 100644 .claude/commands/draft-req.md create mode 100644 .claude/commands/new-discovery.md create mode 100644 .claude/commands/review-discovery.md create mode 100644 .claude/commands/run-batch-implementation.md create mode 100644 .claude/commands/run-sdlc.md create mode 100644 .claude/commands/suggest-batch-reqs.md create mode 100644 .claude/commands/suggest-next-discovery.md create mode 100644 CLAUDE.md create mode 100644 docs/discovery/dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md diff --git a/.claude/commands/bootstrap-baseline.md b/.claude/commands/bootstrap-baseline.md new file mode 100644 index 0000000..2e6e18f --- /dev/null +++ b/.claude/commands/bootstrap-baseline.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/bootstrap-baseline/SKILL.md` exactly. diff --git a/.claude/commands/capture-release-feedback.md b/.claude/commands/capture-release-feedback.md new file mode 100644 index 0000000..0604399 --- /dev/null +++ b/.claude/commands/capture-release-feedback.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/capture-release-feedback/SKILL.md` exactly. diff --git a/.claude/commands/change-req.md b/.claude/commands/change-req.md new file mode 100644 index 0000000..743e120 --- /dev/null +++ b/.claude/commands/change-req.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/change-req/SKILL.md` exactly. diff --git a/.claude/commands/confirm-batch-verification.md b/.claude/commands/confirm-batch-verification.md new file mode 100644 index 0000000..286652b --- /dev/null +++ b/.claude/commands/confirm-batch-verification.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/confirm-batch-verification/SKILL.md` exactly. diff --git a/.claude/commands/confirm-discovery.md b/.claude/commands/confirm-discovery.md new file mode 100644 index 0000000..f5767be --- /dev/null +++ b/.claude/commands/confirm-discovery.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/confirm-discovery/SKILL.md` exactly. diff --git a/.claude/commands/confirm-release.md b/.claude/commands/confirm-release.md new file mode 100644 index 0000000..6b7b2a0 --- /dev/null +++ b/.claude/commands/confirm-release.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/confirm-release/SKILL.md` exactly. diff --git a/.claude/commands/confirm-req-implemented.md b/.claude/commands/confirm-req-implemented.md new file mode 100644 index 0000000..7ac5496 --- /dev/null +++ b/.claude/commands/confirm-req-implemented.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/confirm-req-implemented/SKILL.md` exactly. diff --git a/.claude/commands/confirm-req.md b/.claude/commands/confirm-req.md new file mode 100644 index 0000000..c55db18 --- /dev/null +++ b/.claude/commands/confirm-req.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/confirm-req/SKILL.md` exactly. diff --git a/.claude/commands/draft-batch-design.md b/.claude/commands/draft-batch-design.md new file mode 100644 index 0000000..b300379 --- /dev/null +++ b/.claude/commands/draft-batch-design.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/draft-batch-design/SKILL.md` exactly. diff --git a/.claude/commands/draft-batch-planning.md b/.claude/commands/draft-batch-planning.md new file mode 100644 index 0000000..92f505e --- /dev/null +++ b/.claude/commands/draft-batch-planning.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/draft-batch-planning/SKILL.md` exactly. diff --git a/.claude/commands/draft-batch-verification.md b/.claude/commands/draft-batch-verification.md new file mode 100644 index 0000000..34cd2c2 --- /dev/null +++ b/.claude/commands/draft-batch-verification.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/draft-batch-verification/SKILL.md` exactly. diff --git a/.claude/commands/draft-batch.md b/.claude/commands/draft-batch.md new file mode 100644 index 0000000..cf0e34a --- /dev/null +++ b/.claude/commands/draft-batch.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/draft-batch/SKILL.md` exactly. diff --git a/.claude/commands/draft-release.md b/.claude/commands/draft-release.md new file mode 100644 index 0000000..b8a0266 --- /dev/null +++ b/.claude/commands/draft-release.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/draft-release/SKILL.md` exactly. diff --git a/.claude/commands/draft-req.md b/.claude/commands/draft-req.md new file mode 100644 index 0000000..373dccd --- /dev/null +++ b/.claude/commands/draft-req.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/draft-req/SKILL.md` exactly. diff --git a/.claude/commands/new-discovery.md b/.claude/commands/new-discovery.md new file mode 100644 index 0000000..8e73514 --- /dev/null +++ b/.claude/commands/new-discovery.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/new-discovery/SKILL.md` exactly. diff --git a/.claude/commands/review-discovery.md b/.claude/commands/review-discovery.md new file mode 100644 index 0000000..e459ab1 --- /dev/null +++ b/.claude/commands/review-discovery.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/review-discovery/SKILL.md` exactly. diff --git a/.claude/commands/run-batch-implementation.md b/.claude/commands/run-batch-implementation.md new file mode 100644 index 0000000..fa4fe14 --- /dev/null +++ b/.claude/commands/run-batch-implementation.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/run-batch-implementation/SKILL.md` exactly. diff --git a/.claude/commands/run-sdlc.md b/.claude/commands/run-sdlc.md new file mode 100644 index 0000000..7519b14 --- /dev/null +++ b/.claude/commands/run-sdlc.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/run-sdlc/SKILL.md` exactly. diff --git a/.claude/commands/suggest-batch-reqs.md b/.claude/commands/suggest-batch-reqs.md new file mode 100644 index 0000000..5f1c5f0 --- /dev/null +++ b/.claude/commands/suggest-batch-reqs.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/suggest-batch-reqs/SKILL.md` exactly. diff --git a/.claude/commands/suggest-next-discovery.md b/.claude/commands/suggest-next-discovery.md new file mode 100644 index 0000000..b6da810 --- /dev/null +++ b/.claude/commands/suggest-next-discovery.md @@ -0,0 +1 @@ +Follow the instructions in `.github/skills/suggest-next-discovery/SKILL.md` exactly. diff --git a/.github/skills/new-discovery/SKILL.md b/.github/skills/new-discovery/SKILL.md index 144494c..b7ad283 100644 --- a/.github/skills/new-discovery/SKILL.md +++ b/.github/skills/new-discovery/SKILL.md @@ -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/.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/.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/.md` 파일을 생성한다. +16. `기존 Discovery 갱신`이면 대상 Discovery 문서를 갱신한다. +17. 아래 플레이스홀더를 우선 치환한다. - `{{DOC_STATUS:draft|review|confirmed}}` -> `draft` - `{{DISCOVERY_ID:dcy-<3자리>__}}` -> 계산한 `DISCOVERY_ID` - `{{ISSUE_NAME:짧은 한글 또는 영문 이슈명}}` -> 입력 원문 또는 요약 이슈명 @@ -311,23 +296,13 @@ Discovery 문서의 `# 3. 문제점의 요약` 중 `현재 상태`를 채우기 - `{{FOLLOW_UP_DISCOVERY_REF:없음 또는 docs/discovery/.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 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..8c0c4dd --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,71 @@ + +# SDLC Governance Instructions + +이 워크스페이스의 AI 에이전트는 Agile 중심 반복형 SDLC를 따른다. +모든 작업은 3-phase 구조와 그 안의 단위별 게이트를 기준으로 수행하며, 임의 단계 스킵은 허용되지 않는다(긴급 핫픽스 예외는 별도 규칙 적용). + +## Lifecycle Phases + +1. Requirements +2. Delivery +3. Release & Feedback + +## Governing Units + +1. Discovery: 문제 정의 단위 +2. REQ: 승인 가능한 요구사항 단위 +3. Batch: 함께 계획, 설계, 구현, 검증하는 delivery 단위 +4. Release: 함께 배포하고 운영 환류를 기록하는 단위 + +## Bootstrap Baseline Path + +- 프로젝트 시작 시 baseline 문서와 active index는 `bootstrap-baseline`으로 먼저 초기화한다. +- `bootstrap-baseline`은 3-phase lifecycle 밖의 bootstrap 단계이며 별도 governance unit가 아니다. +- 첫 real Discovery는 baseline 초기화 이후 실제 제품/서비스 변경 주제로 시작한다. + +## Default Flow + +1. Bootstrap: `bootstrap-baseline` (baseline 문서와 active index가 비어 있을 때만) +2. Requirements: `new-discovery` -> `confirm-discovery` -> `draft-req` -> `confirm-req` -> `suggest-batch-reqs` -> `draft-batch` +3. Delivery: `draft-batch-planning` -> `draft-batch-design` -> `run-batch-implementation` -> `draft-batch-verification` -> `confirm-batch-verification` -> `confirm-req-implemented` +4. Release & Feedback: `draft-release` -> `confirm-release` -> `capture-release-feedback` + +## Lightweight Change Path + +- 단일 저위험 `Approved` REQ이고 구조/인터페이스/런타임 흐름 영향이 없으면 `minor-change` fast path를 사용할 수 있다. +- 이 경로는 `suggest-batch-reqs`를 생략하고 `draft-batch`로 바로 `batch-lite` batch를 만든다. +- `batch-lite`는 planning부터 시작하고, design은 필요할 때만 생성한다. +- release는 `docs-only`, `tooling`, `app-service` profile 중 하나를 선택해 검증 강도를 조정한다. + +## Change Management Extension + +- 기존 REQ 본문을 수정할 때는 `change-req`를 사용해 Change Log 근거를 먼저 남긴다. +- release feedback의 후속 입력은 `Discovery Input`, `REQ Input`, `Change Request Input`으로 분리해 기록한다. +- 다음 반복 후보만 먼저 정리하려면 `suggest-next-discovery`를 사용하고, 실제 문서 생성은 `new-discovery`로 이어 간다. + +## Stage Mapping + +- Discovery는 Requirements phase 안에서 유지한다. +- Planning, Design, Implementation, Verification은 Batch 내부 stage로 다룬다. +- Release와 Operations는 Release & Feedback phase 내부에서 다룬다. +- `review-*` stage command는 더 이상 active flow에 포함하지 않고 대응 `confirm-*` 절차에 흡수한다. +- prompt 기반 stage command는 active 경로에서 사용하지 않고 `.github/skills/` 아래 skill entrypoint만 사용한다. + +## Global Rules + +1. 증거 기반: 요구사항, 가정, 리스크, 결정 근거를 문서에 남긴다. +2. 게이트 준수: 각 phase와 단위의 DoR(진입 조건)과 DoD(완료 조건)을 충족해야 다음 단계로 이동한다. +3. 테스트 우선 검증: 구현 결과는 테스트 또는 검증 근거 없이 완료로 간주하지 않는다. +4. 변경 영향도 기록: 코드/문서/운영 영향 범위를 명시한다. +5. 불확실성 우선 해소: 차단 이슈가 있으면 임의 추정 대신 질문 또는 추가 탐색을 수행한다. +6. 운영 환류: 운영 단계 인사이트는 다음 Discovery의 입력으로 반드시 반영한다. + +## Hotfix Exception Path + +긴급 핫픽스는 Requirements/Delivery 설계를 경량화할 수 있다. 단, 아래는 필수다. + +1. 최소 요구사항 정의(증상, 영향, 성공 조건) +2. 최소 검증(재현 테스트 또는 핵심 시나리오 확인) +3. 배포 전 롤백 계획 +4. 배포 후 Postmortem 작성 및 다음 스프린트 환류 + diff --git a/docs/discovery/dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md b/docs/discovery/dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md new file mode 100644 index 0000000..87bf880 --- /dev/null +++ b/docs/discovery/dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md @@ -0,0 +1,235 @@ +# 0. 문서 상태 +이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다. + +- 상태: draft +- 문서 ID: dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution +- 이슈명: portfolio_id UUID 교체 및 CLI 사용자 범위 기반 자산 식별 구조 전환 +- 작성 시각(KST): 2026-05-11 00:00 +- 마지막 갱신 시각(KST): 2026-05-11 00:00 +- 대체됨: 없음 +- 후속 Discovery 참조: 없음 +- 생성된 REQ 참조: 없음 + +# 1. 계획 상태 요약 +현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다. + +- 연계 문서 현황: + - 관련 계약 문서: docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md (A-3: asset_id는 portfolio_id를 그대로 사용) + - 관련 TODO/메모: 없음 +- 해석: + - 현재 `portfolio_id`는 사용자가 직접 지정하는 전역 고유 문자열이어서 다중 사용자 환경에서 이름 충돌이 발생하고, CLI 뮤테이션 명령이 소유권 검증 없이 portfolio_id만으로 실행된다. + - 이번 Discovery는 `portfolio_id`를 서버 생성 UUID로 교체하고 사용자 표시용 `name`을 `(owner_user_id, name)` 복합 유니크 제약으로 관리하는 구조 전환 전체 범위를 정의한다. + +# 2. 요구사항 판정 결과 +이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다. + +- 판정: 신규 +- 근거 + - 기존 dcy-001은 DB 마이그레이션 검증, dcy-002는 trex-basic 소비자 API 계약, dcy-003은 portfolio list --user 필수화를 다루며, portfolio_id 식별자 체계 전환을 다루는 Discovery가 없다. + - `portfolio_id`를 UUID로 교체하고 `(owner_user_id, name)` 복합 유니크 제약을 도입하는 것은 DB 스키마, 도메인 모델, CLI 인터페이스, HTTP API 경로, 소비자 계약 전반에 영향하는 독립적인 구조 변경 주제다. + +# 3. 문제점의 요약 +문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다. + +- 현재 상태 + - `portfolios.portfolio_id`는 TEXT PRIMARY KEY로 사용자가 직접 지정하는 전역 단일 네임스페이스다. alice가 `005930:tv`를 먼저 생성하면 bob은 동일 이름을 사용할 수 없다. + - CLI 뮤테이션 명령(`buy`, `sell`, `invest`, `transfer`, `reset`, `delete`, `status`, `update`)은 `portfolio_id`를 Argument로만 받고 소유자 검증을 하지 않는다. 권한 있는 운영자가 다른 사용자 소유의 portfolio를 portfolio_id만 알면 조작할 수 있다. + - `ledger_entries`(portfolio_ledger), `portfolio_comments`, `portfolio_tags`, `ledger_trades` 테이블이 `portfolio_id` TEXT를 FK로 참조한다. + - dcy-002 A-3에 따라 `GET /v1/assets`의 `asset_id` 응답 필드가 `portfolio_id`를 그대로 반환하므로, trex-basic 데몬이 `asset_id`로 ledger 기록 등 후속 API를 호출한다. + - `Portfolio` dataclass(`app/domain/models.py`)와 PostgreSQL 레포지터리 전반이 `portfolio_id` 문자열을 기준으로 설계되어 있다. +- 기대 상태 + - `portfolios.portfolio_id`는 서버가 발급하는 UUID(TEXT 또는 UUID 타입)로 교체된다. 사용자는 create 시 `name`만 지정하면 된다. + - `name` 컬럼은 `(owner_user_id, name)` 복합 UNIQUE 제약으로 같은 사용자 내에서 유일하게 관리된다. 다른 사용자는 동일 `name`을 사용할 수 있다. + - CLI 뮤테이션 명령은 `--user ` 조합으로 portfolio를 식별하고, 내부적으로 UUID를 조회해 처리한다. 소유권 검증이 명령 실행 경로에 포함된다. + - HTTP API 경로는 UUID를 path parameter로 사용하며, `GET /v1/assets`의 `asset_id`도 UUID를 반환한다. + - 기존 데이터는 마이그레이션으로 새 UUID를 할당받고, 기존 `portfolio_id` 문자열은 `name` 컬럼으로 이전된다. +- 이해관계자 + - portfolio-hub 유지보수 담당자 (구현 주체) + - trex-basic 팀 (GET /v1/assets asset_id 필드 변경 영향을 받는 소비자) + - CLI 운영자 (명령 인터페이스 변경 대상) +- 제약사항 + - 기존 Alembic revision chain을 깨지 않는 IF NOT EXISTS 기반 migration을 추가한다(dcy-001/REQ-002 정책 준수). + - dcy-002 A-3("asset_id는 portfolio_id를 그대로 사용")은 이번 Discovery에서 철회된다. trex-basic 팀에게 breaking change를 사전 통보해야 한다. + - `name`은 owner 내에서 유일하되, 허용 문자 범위(공백, 특수문자 등)는 REQ 단계에서 결정한다. + +## 주요 사용자 시나리오 +사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다. + +- 운영자가 `pfhub portfolio create tv --symbol 005930 --user alice --cash-balance 10000000 --force`로 포트폴리오를 생성하면 서버가 UUID를 부여하고, 이후 `pfhub portfolio buy tv --user alice --quantity 10 --price 71000 --force`로 alice의 `tv` 포트폴리오를 정확히 조작한다. bob이 같은 이름 `tv`를 가진 포트폴리오를 생성해도 독립된 레코드로 관리된다. +- trex-basic 데몬이 `GET /v1/assets`를 호출하면 `asset_id`로 UUID를 수신하고, 이후 `POST /v1/assets/{asset_id}/ledger/trades`에 UUID를 사용해 체결 내역을 기록한다. UUID 도입으로 asset_id가 전역 유일하게 보장된다. +- 기존에 `005930:tv`라는 portfolio_id로 운영 중인 데이터가 있을 때, 마이그레이션 후 기존 레코드의 `name`이 `005930:tv`로 이전되고 새 UUID가 `portfolio_id`로 할당된다. ledger, comments 등 FK 참조도 새 UUID로 함께 갱신된다. + +# 4. 이번에 정의할 변경 +이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다. + +- `portfolios.portfolio_id` PRIMARY KEY를 서버 생성 UUID로 교체하고 `name` TEXT 컬럼을 신규 추가: `(owner_user_id, name)` 복합 UNIQUE 제약 적용, 기존 portfolio_id 문자열을 name으로 이전하는 데이터 마이그레이션 포함 +- CLI 뮤테이션 명령 식별 방식 전환: 모든 뮤테이션 명령에서 `portfolio_id` Argument를 `` + `--user ` 조합으로 교체하고, 내부에서 `(owner_user_id, name)` → UUID 조회 후 처리 +- HTTP API 경로 및 GET /v1/assets asset_id 전환: path parameter와 응답 필드를 UUID 기반으로 변경, dcy-002 A-3 철회 및 trex-basic 계약 갱신 + +## 영향 범위 +변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다. + +- 코드 영향: + - `migrations/versions/`: portfolios PK 교체, name 컬럼 추가, (owner_user_id, name) UNIQUE 제약, 기존 데이터 이전 마이그레이션 + - `app/domain/models.py`: Portfolio dataclass portfolio_id → UUID, name 필드 명확화 + - `app/repositories/postgres.py`: create_portfolio(서버 UUID 생성), get_portfolio_by_name_and_user() 신규, 모든 portfolio_id 참조 업데이트 + - `app/domain/services.py`: transfer, buy, sell 등 서비스 메서드 시그니처 — (user_id, name) → UUID 해석 추가 + - `app/cli/commands/portfolio.py`: status, buy, sell, invest, transfer, reset, delete, update 명령의 Argument 교체 + - `app/api/portfolios.py` (HTTP API): path parameter UUID 기반 전환 + - `app/api/v1_assets.py`: asset_id 응답 필드를 UUID로 반환 + - `app/schemas/portfolio.py`, `app/schemas/v1.py`: asset_id/portfolio_id 필드 타입 문서화 +- 문서 영향: + - `docs/data-model.md`: portfolios 테이블 스키마 변경 반영 + - `docs/interface-contract.md`: GET /v1/assets asset_id 변경 반영 + - `docs/project-structure.md`: 갱신 필요 (repositories, services 변경 반영) + - `docs/runtime-flows.md`: 갱신 필요 (CLI 명령 흐름, v1 API 흐름 변경 반영) + - `docs/discovery/dcy-002_*`: A-3 철회 주석 추가 +- 운영 영향: + - trex-basic 팀에게 asset_id 필드값이 UUID로 바뀜을 사전 통보 필요 + - CLI 운영 스크립트에서 portfolio_id 직접 지정 방식을 `--user + name` 방식으로 교체 필요 + - 기존 운영 runbook 갱신 필요 + +# 5. 요구사항 목록 +실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다. + +## 기능 요구사항 +- FR-1: `portfolios.portfolio_id`를 서버 생성 UUID(TEXT)로 교체한다. 기존 사용자 지정 portfolio_id 문자열은 `portfolios.name` TEXT 컬럼으로 이전한다. `(owner_user_id, name)` 복합 UNIQUE 제약을 DB 레벨에서 보장한다. +- FR-2: `portfolio create` CLI 명령은 `name` Argument와 `--user` 옵션을 필수로 받고, `portfolio_id`는 서버가 UUID로 발급한다. 사용자는 UUID를 직접 지정하거나 조회할 수 없다. +- FR-3: CLI 뮤테이션 명령(`status`, `buy`, `sell`, `invest`, `transfer`, `reset`, `delete`, `update`)은 `` Argument와 `--user ` 옵션으로 portfolio를 식별한다. 내부에서 `(owner_user_id, name)` → `portfolio_id(UUID)`를 조회한 뒤 처리한다. `name` + `--user` 조합으로 portfolio를 찾지 못하면 명확한 오류를 반환한다. +- FR-4: HTTP API의 portfolio 관련 path parameter를 UUID 기반으로 전환한다. `GET /v1/assets` 응답의 `asset_id` 필드는 UUID를 반환한다. dcy-002 A-3을 이번 Discovery에서 철회한다. +- FR-5: 기존 데이터 마이그레이션 — 현재 `portfolio_id` 문자열 값을 `name` 컬럼으로 복사하고, 각 레코드에 새 UUID를 `portfolio_id`로 할당한다. `portfolio_ledger`, `portfolio_comments`, `portfolio_tags`, `ledger_trades` 등 FK 참조 테이블의 portfolio_id도 새 UUID로 함께 갱신한다. +- FR-6: `docs/project-structure.md`와 `docs/runtime-flows.md`를 이번 변경 내용에 맞게 갱신한다(repositories/services 인터페이스 변경, CLI 흐름, v1 API 흐름 변경 반영). + +## 비기능 요구사항 +성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다. + +- NFR-1: 데이터 마이그레이션은 단일 Alembic revision으로 수행하며, IF NOT EXISTS 패턴을 준수해 재실행 시 오류가 없어야 한다(REQ-002 준수). FK 참조 테이블과의 갱신은 트랜잭션 내에서 atomic하게 처리한다. +- NFR-2: CLI `(owner_user_id, name)` → UUID 조회는 단일 DB 쿼리로 처리하며, 조회 실패 시 명확한 오류 메시지(`포트폴리오를 찾을 수 없습니다: {name} (user: {username})`)를 출력해야 한다. +- NFR-3: trex-basic 계약 변경(asset_id UUID 전환)은 배포 전에 trex-basic 팀에게 통보하고, 변경 일정을 docs/interface-contract.md에 기록해야 한다. + +## 범위 경계 +이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다. + +- In Scope + - `portfolios.portfolio_id` UUID 교체 및 `name` 컬럼 추가 + - `(owner_user_id, name)` 복합 UNIQUE 제약 + - 기존 데이터 마이그레이션 (FK 참조 포함) + - CLI 뮤테이션 명령 식별 방식 전환 (`--user + name`) + - HTTP API path parameter UUID 전환 + - `GET /v1/assets` asset_id UUID 반환 + - `docs/project-structure.md`, `docs/runtime-flows.md` 갱신 + - `docs/interface-contract.md`, `docs/data-model.md` 갱신 +- Out of Scope + - trex-basic 측 코드 변경 — portfolio-hub API 변경만 담당 + - `name` 변경 이력 감사 로그 — 향후 반복으로 Deferred + - `name` 허용 문자 유효성 검사 정책 — REQ 단계에서 결정 + - HTTP API에서 `(username, name)` 조합으로 portfolio를 조회하는 엔드포인트 추가 — {{OUT_OF_SCOPE_API_NAME_LOOKUP}} 결정 필요 + +# 6. 리스크/가정 목록 +불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다. + +## 리스크 +- R-1 (High): 기존 FK 참조 테이블(`portfolio_ledger`, `portfolio_comments`, `portfolio_tags`, `ledger_trades`)의 portfolio_id를 새 UUID로 일괄 갱신하는 마이그레이션 중 오류 발생 시 데이터 불일치가 생길 수 있다. + - 완화 방안: 마이그레이션 전 DB 전체 백업 수행. 마이그레이션 스크립트를 단일 트랜잭션으로 작성하고, 검증 쿼리(FK 고아 레코드 0건 확인)를 마이그레이션 스크립트 마지막에 실행한다. +- R-2 (High): `GET /v1/assets` `asset_id`가 UUID로 바뀌면 trex-basic 데몬의 `POST /v1/assets/{asset_id}/ledger/trades` 경로가 즉시 동작하지 않는다. 배포 타이밍 불일치 시 운영 장애가 발생한다. + - 완화 방안: trex-basic 팀과 변경 일정 사전 조율. portfolio-hub 배포 전 trex-basic 코드 업데이트가 선행되거나 동시 배포한다. 임시 호환성 레이어(기존 name으로 fallback 조회) 필요 여부를 REQ 단계에서 결정한다(OQ-1). +- R-3 (Medium): `name`을 mutable로 허용하면 CLI 스크립트나 외부 참조에서 portfolio를 name으로 식별하던 코드가 name 변경 후 깨진다. + - 완화 방안: name을 immutable(생성 후 변경 불가)로 정책을 확정하거나, 변경 시 경고와 함께 명시적 확인 절차를 요구한다. 결정은 OQ-2에서 처리한다. + +## 가정 +아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다. + +- A-1: `portfolio_id`(UUID)는 서버에서 `uuid.uuid4()`로 생성하며, 사용자가 직접 지정하거나 예측할 수 없다. +- A-2: `name`은 `(owner_user_id, name)` 복합 UNIQUE 제약을 만족하면 되며, 전역 유일성은 요구하지 않는다. +- A-3: 기존 `portfolio_id` 문자열(`005930:tv` 형식)은 데이터 마이그레이션 시 `name` 컬럼 값으로 그대로 이전한다. 변환 없이 복사한다. +- A-4: HTTP API 경로에서 `(username, name)` 조합 조회 엔드포인트 추가는 이번 반복 Out of Scope로 잠정 처리하고, CLI 경로만 먼저 전환한다. + +## 오픈 질문 +답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다. + +- OQ-1: trex-basic 계약 호환성 전략 — `GET /v1/assets` asset_id가 UUID로 바뀔 때 trex-basic 측의 대응 준비 일정이 확정되기 전에 portfolio-hub를 먼저 배포할 수 있는지, 아니면 임시 호환 레이어(name으로 fallback 조회)가 필요한지. + - 상태: Open + - 처리 방안: trex-basic 팀과 협의 후 결정. 배포 순서 또는 호환 레이어 필요 여부를 REQ 단계 진입 전에 확정한다. + - 종료 조건: trex-basic 팀 확인 완료 또는 임시 호환 레이어 구현 방안 확정 시 Answered 처리. +- OQ-2: `name` mutable 정책 — 생성 이후 name 변경을 허용할지 여부. 허용할 경우 기존 CLI 스크립트 참조 안정성 확보 방안. + - 상태: Open + - 처리 방안: 사용자(Justin) 결정. 단순성을 위해 immutable을 기본 제안으로 두고 확인한다. + - 종료 조건: 사용자 확인 후 Answered 처리. 결과를 NFR 또는 FR에 반영. +- OQ-3: HTTP API에서 `(username, name)` 조합으로 portfolio를 조회하는 엔드포인트 추가 여부 — 외부 API 소비자가 UUID를 직접 관리해야 하는 부담을 줄이기 위해 `/portfolios?user=alice&name=tv` 형태의 조회 경로가 필요한지. + - 상태: Open + - 처리 방안: 사용자(Justin) 결정. 현재 trex-basic은 GET /v1/assets로 UUID를 조회하므로 별도 엔드포인트 불필요할 수 있다. + - 종료 조건: 사용자 확인 후 Answered 또는 Deferred 처리. + +# 7. 초기 성공 기준 +이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다. + +- S-1: `pfhub portfolio create tv --symbol 005930 --user alice --force` 실행 시 UUID가 portfolio_id로 발급되고, alice와 bob이 동일 name `tv`로 각각 portfolio를 생성할 수 있다. +- S-2: `pfhub portfolio buy tv --user alice --quantity 10 --price 71000 --force`가 alice 소유의 `tv` portfolio에만 적용되고, `--user bob`으로는 alice의 portfolio를 조작할 수 없다. +- S-3: 마이그레이션 후 기존 데이터의 `portfolio_ledger`, `portfolio_comments` 등 FK 참조 테이블에 고아 레코드(orphan)가 0건이고, `GET /v1/assets` 응답의 `asset_id`가 UUID 형식이다. +- S-4: `docs/project-structure.md`, `docs/runtime-flows.md`, `docs/data-model.md`, `docs/interface-contract.md`가 변경 내용을 반영해 갱신된다. + +## 측정 방식 및 데이터 출처 +각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다. + +- S-1 측정 방식: pytest — portfolio create 후 portfolio_id가 UUID 형식(`re.match(r'^[0-9a-f-]{36}$', ...)`)임을 검증. alice/bob 동일 name 독립 생성 테스트 / 데이터 출처: `tests/test_cli.py` 또는 신규 `tests/test_portfolio_uuid.py` +- S-2 측정 방식: pytest — `--user bob`으로 alice 소유 portfolio 조작 시 오류 반환 검증 / 데이터 출처: `tests/test_cli.py` 소유권 검증 케이스 +- S-3 측정 방식: 마이그레이션 스크립트 내 검증 쿼리 실행 결과 0건 확인 + pytest `test_v1.py::test_v1_assets_*` asset_id UUID 형식 검증 / 데이터 출처: `migrations/versions/` 마이그레이션 스크립트, `tests/test_v1.py` +- S-4 측정 방식: 각 baseline 문서에 CLI 흐름, repositories/services 인터페이스, v1 API asset_id UUID 내용이 포함됐는지 코드 리뷰로 확인 / 데이터 출처: `docs/project-structure.md`, `docs/runtime-flows.md`, `docs/data-model.md`, `docs/interface-contract.md` + +# 8. REQ로 넘기기 전 확인 체크 +REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다. + +- [ ] 범위(In Scope/Out of Scope) 확정 + - 기준: OQ-3(HTTP API name 조회 엔드포인트) 결정 완료, Out of Scope 경계 승인 +- [ ] 성공 지표의 측정 방식/데이터 출처 확정 + - 기준: S-1~S-4 측정 방식이 pytest 또는 코드 리뷰로 추적 가능한 형태로 기술됨 +- [ ] High 영향 리스크 우선순위 및 해소 책임자 지정 + - 기준: R-1(마이그레이션 데이터 무결성), R-2(trex-basic 계약 파괴) 완화 방안 확정 및 담당자 지정 +- [ ] 모든 오픈 질문(OQ) `Open` 상태 없음 확인 + - 기준: OQ 목록에 `Open` 상태 항목이 0개이거나, 잔여 항목 전부 `Deferred` 처리 완료 +- [ ] Freeze 확정 담당자(CONFIRMED_BY) 지정 + - 기준: Justin 또는 지정된 승인자가 confirm-discovery skill로 Freeze 확정 + +# 9. 파일 처리 결과 +이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다. + +- 처리 결과: 생성 +- 생성 경로: docs/discovery/dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md +- 참조 문서: + - docs/discovery/dcy-002_20260502_trex-basic-consumer-api-contract.md (A-3 철회 대상) + - docs/discovery/dcy-003_20260502_portfolio-list-user-required.md (--user 필수화 선행 작업) + - app/domain/models.py + - app/cli/commands/portfolio.py + - app/repositories/postgres.py + - migrations/versions/20260403_0001_initial_portfolio_schema.py + +# 10. 사용자 결정 필요 항목 요약 +사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다. + +## DECIDE +- {{DECIDE_NAME_MUTABILITY}}: `name` 컬럼의 변경 허용 여부 — immutable(생성 후 변경 불가) 또는 mutable(변경 허용, 단 확인 절차 필요) 중 선택 (OQ-2) +- {{DECIDE_TREX_COMPAT_STRATEGY}}: trex-basic 계약 호환성 전략 — portfolio-hub 단독 배포 후 trex-basic 후속 배포 허용 여부, 또는 임시 호환 레이어(name fallback 조회) 구현 필요 여부 (OQ-1) + +## CONFIRM +- {{CONFIRM_API_NAME_LOOKUP_SCOPE}}: HTTP API에서 `(username, name)` 조합 조회 엔드포인트 추가가 이번 반복 Out of Scope임을 확인 (OQ-3) +- {{CONFIRM_MIGRATION_STRATEGY}}: 기존 portfolio_id 문자열을 name으로 변환 없이 그대로 복사하는 마이그레이션 전략 확인 (A-3) + +## DATA +- {{DATA_NAME_ALLOWED_CHARS}}: `name` 컬럼에 허용할 문자 범위 정의 — 공백 허용 여부, 특수문자 허용 범위, 최대 길이 제한 등 (REQ 단계 결정 필요) + +# 11. Discovery Freeze +REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다. + +## 섹션 참조 +- 범위: [# 5. 요구사항 목록 > 범위 경계](#5-요구사항-목록) +- 리스크/오픈 질문: [# 6. 리스크/가정 목록](#6-리스크가정-목록) +- 성공 기준: [# 7. 초기 성공 기준](#7-초기-성공-기준) +- 인계 전 확인: [# 8. REQ로 넘기기 전 확인 체크](#8-req로-넘기기-전-확인-체크) +- 사용자 결정 필요: [# 10. 사용자 결정 필요 항목 요약](#10-사용자-결정-필요-항목-요약) + +## Freeze 플래그 +- Handoff Decision: 보류 +- Handoff Rationale: 초기 Discovery 초안 생성 완료. OQ-1(trex-basic 호환성), OQ-2(name mutable 여부), OQ-3(HTTP API name 조회 엔드포인트) 3개가 Open 상태이며 REQ 초안 작성 전 사용자 확인 필요. +- Ready for REQ Drafting: false +- Confirmed By: TBD +- Confirmed At (KST): TBD diff --git a/docs/discovery/index.md b/docs/discovery/index.md index 7c69765..0245c92 100644 --- a/docs/discovery/index.md +++ b/docs/discovery/index.md @@ -8,4 +8,5 @@ |---|---|---|---|---| | dcy-001_20260430_real-db-migration-validation-and-operations-readiness | 20260430 | 실DB 마이그레이션 검증 및 운영 준비 | [Discovery](./dcy-001_20260430_real-db-migration-validation-and-operations-readiness.md) | confirmed | | dcy-002_20260502_trex-basic-consumer-api-contract | 20260502 | trex-basic Consumer-Driven Contract 반영 — service-token runtime_id 발급 및 v1 API 엔드포인트 구현 | [Discovery](./dcy-002_20260502_trex-basic-consumer-api-contract.md) | confirmed | -| dcy-003_20260502_portfolio-list-user-required | 20260502 | CLI `pfhub portfolio list` — `--user` 옵션 필수화 및 소유자 기반 조회 강제 | [Discovery](./dcy-003_20260502_portfolio-list-user-required.md) | confirmed | \ No newline at end of file +| dcy-003_20260502_portfolio-list-user-required | 20260502 | CLI `pfhub portfolio list` — `--user` 옵션 필수화 및 소유자 기반 조회 강제 | [Discovery](./dcy-003_20260502_portfolio-list-user-required.md) | confirmed | +| dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution | 20260511 | portfolio_id UUID 교체 및 CLI 사용자 범위 기반 자산 식별 구조 전환 | [Discovery](./dcy-004_20260511_portfolio-id-uuid-migration-and-user-scoped-name-resolution.md) | draft | \ No newline at end of file