draft: Reorganize documentation and update prompts

This commit is contained in:
2026-04-13 23:26:54 +09:00
parent 0fcde8b89b
commit e89690b1dd
7 changed files with 128 additions and 283 deletions
@@ -0,0 +1,50 @@
---
description: "Use when customizing REQ candidate discovery rules for /reopen-requirement-status command, including keyword dictionary, scoring, tie-breaks, and normalization policy."
applyTo: ".github/prompts/reopen-requirement-status.prompt.md"
---
# Reopen Requirement Discovery Guidelines
## 목적
`/reopen-requirement-status` 입력에 REQ ID가 없을 때, 관련 REQ 후보를 일관된 기준으로 탐색하고 우선순위를 정한다.
## 후보 탐색 우선순위
1. 계약 키워드 일치
- `API`, `endpoint`, `request`, `response`, `schema`, `field`, `CLI`, `command`, `option`, `UI`, `event`, `config`, `env`, `deploy`, `integration`
2. 영향 영역 일치
- 입력의 변경 대상 모듈/문서/테스트와 REQ의 `Impacted Area` 교집합
3. 목적/행동 일치
- 입력의 동사/의도(추가, 제거, 변경, 완화, 강화, 비활성화 등)와 REQ `Intent`/`Requirement`의 의미 유사도
4. 상태 가중치
- 현재 상태가 `Approved`, `Implemented`, `Deprecated`인 REQ 우선
## 점수 및 신뢰도
- 점수식: `키워드(0-5) + 영향영역(0-3) + 의미유사(0-2) + 상태가중치(0-1)`
- 정렬: 총점 내림차순
- 신뢰도:
- `High(7-11)`
- `Medium(4-6)`
- `Low(0-3)`
## 도메인 키워드 사전 (커스터마이즈 가능)
- Auth & Access: `auth`, `login`, `oauth`, `token`, `permission`, `rbac`, `role`, `scope`
- Billing & Subscription: `billing`, `invoice`, `payment`, `subscription`, `plan`, `quota`, `credit`
- Data & Migration: `schema`, `migration`, `backfill`, `etl`, `import`, `export`, `retention`
- API & Contract: `api`, `endpoint`, `request`, `response`, `versioning`, `webhook`, `payload`
- Runtime & Operations: `deploy`, `rollback`, `release`, `monitoring`, `alert`, `slo`, `incident`
- Configuration: `config`, `env`, `feature flag`, `toggle`, `secret`, `parameter`
- UX & Interface: `ui`, `ux`, `screen`, `form`, `flow`, `command`, `cli`, `option`
- Testing & Quality: `test`, `e2e`, `regression`, `coverage`, `validation`, `acceptance`
## 정규화 규칙
- 사전에 없는 표현이 입력에 등장하면 의미가 유사한 사전 키워드로 1회 정규화해 근거에 표기한다.
- 예: `권한` -> `permission`, `과금` -> `billing`
## 동점 처리
- 동일 점수 후보가 여러 개면 최신 Change Log 항목이 있는 REQ를 우선한다.
- 여전히 동점이면 현재 active 상태(`Approved`/`Implemented`) REQ를 우선한다.
- 추가 동점이면 REQ ID가 작은 항목을 우선한다.
## 출력 권장
- 후보는 최대 5개 제시
- 각 후보에 `REQ ID`, `신뢰도`, `점수`, `근거 키워드`, `영향 영역`을 포함
- 확정 전에는 `Immediate Questions`로 최종 대상 REQ 선택을 먼저 요청
@@ -0,0 +1,44 @@
---
description: "Use when: move Approved, Implemented, or Deprecated requirements back to Proposed (or Re-review) with decision checkpoints, conflict candidates, and fallback REQ discovery"
name: "Reopen Requirement Status"
argument-hint: "(선택) REQ-XXX, REQ-XXX; 변경 의도와 범위 설명"
agent: "agent"
model: "GPT-5 (copilot)"
---
다음 입력을 기준으로 지정된 requirement를 재검토 상태로 되돌리는 변경안을 만든다.
입력:
${input}
입력 해석 규칙:
- 입력 형식은 기본적으로 `REQ-XXX, REQ-XXX; 이렇게 이렇게 변경할거야.` 를 따른다.
- `;` 앞은 대상 REQ ID 목록, 뒤는 변경 의도/배경으로 해석한다.
- 구분자는 쉼표/공백을 모두 허용하되, 최종적으로 중복 없는 REQ ID 목록으로 정규화한다.
- 입력에 REQ ID가 없으면 전체 입력을 변경 의도/배경으로 간주한다.
작업 규칙:
- 기준 문서는 `docs/SRS/index.md`, 해당 REQ 파일, [SRS instructions](../../.github/instructions/srs.instructions.md), [Reopen requirement discovery instructions](../../.github/instructions/reopen-requirement-discovery.instructions.md) 다.
- 대상 REQ ID가 명시되지 않으면 `docs/SRS/index.md` Requirement Register와 REQ 파일 제목/Intent/Requirement/Impacted Area를 기반으로 관련 후보를 탐색한다.
- 후보 탐색, 점수화, 신뢰도, 동점 처리, 도메인 키워드 정규화는 [Reopen requirement discovery instructions](../../.github/instructions/reopen-requirement-discovery.instructions.md)를 그대로 따른다.
- REQ 미지정 시 후보는 최대 5개까지 제시하고, 신뢰도(High/Medium/Low)와 근거(키워드/영향 영역)를 함께 제시한다.
- REQ 미지정 시 확정 전에는 상태 변경안을 단정하지 말고, `Immediate Questions`에서 최종 대상 REQ 확인 질문을 먼저 제시한다.
- 사용자가 후보 중 선택하면 선택된 REQ 기준으로 상태 되돌림 변경안을 완성한다.
- 대상 REQ의 현재 상태가 `Approved`, `Implemented`, `Deprecated` 중 하나인지 확인한다.
- 상태 되돌림의 목표 상태는 기본 `Proposed`로 제안한다.
- 팀이 `재검토 상태`를 별도로 운용하면 목표 상태를 `Re-review`(또는 팀 표기)로 제안할 수 있다. 단, 최종 상태값은 사용자 결정 항목으로 분리한다.
- 각 REQ마다 왜 되돌려야 하는지(계약 변경, acceptance criteria 변경, 리스크 발견, 구현 불일치 등) 근거를 1-2줄로 요약한다.
- 변경 전/후 영향으로 충돌 가능성이 있는 REQ 후보를 `docs/SRS/index.md` Requirement Register 기준으로 제시한다.
- 충돌 후보는 다음 기준으로 찾는다: 동일 기능 영역, 동일 인터페이스/API/CLI/데이터 스키마, 같은 모듈/문서 영향 범위, 기존 acceptance criteria 중복/상충.
- 사용자가 결정해야 할 항목을 별도 섹션으로 분리한다.
- 결정 누락 시 즉시 물어야 할 질문을 먼저 제시한다.
- 실제 문서 변경을 수행하는 대신, 바로 적용 가능한 수정안(상태, Change Log, impacted area 재검토 포인트)을 제시한다.
출력 형식:
1. Reopen Decision
2. Immediate Questions (없으면 `없음`)
3. Detected REQ Candidates (REQ 미지정인 경우 필수, 지정된 경우 생략 가능)
4. User Decisions Required
5. Suggested Status Changes (REQ별: `from -> to`)
6. Conflict Candidate REQs (REQ별 후보 ID와 충돌 이유)
7. Suggested REQ Edits (Status, Intent/Requirement/Acceptance Criteria 영향, Change Log 초안)
8. Next Action
@@ -0,0 +1,34 @@
---
description: "Use when: verify one or more REQ IDs are Approved and create or update the matching docs/technical specifications"
name: "Sync Technical Specs"
argument-hint: "Enter REQ IDs, e.g. REQ-011, REQ-007, REQ-012"
agent: "agent"
model: "GPT-5 (copilot)"
---
다음 입력으로 지정된 requirement ID 목록에 대해, 승인 상태를 확인하고 해당하는 `docs/technical/` 문서를 실제로 갱신한다.
입력:
${input}
작업 규칙:
- 입력에서 `REQ-XXX` 목록을 추출한다. 쉼표 또는 공백으로 구분된 여러 ID를 지원한다.
- 먼저 `docs/SRS/index.md`의 `Requirement Register`와 각 REQ 파일의 `Status`를 함께 확인한다.
- 두 곳 모두 `Approved`인 requirement만 기술명세 업데이트 대상으로 포함한다.
- 하나라도 `Approved`가 아니거나 파일을 찾지 못하면 해당 REQ는 blocker로 보고하고, 그 REQ에 대한 technical doc은 수정하지 않는다.
- `docs/technical/index.md`와 각 technical doc 상단의 `Related REQ`를 기준으로 기존 연결 문서를 찾는다.
- 연결 문서가 있으면 현재 승인된 requirement에 맞게 내용을 실제로 업데이트한다.
- 연결 문서가 없으면 `docs/technical/` 아래에 새 문서를 생성하고 `docs/technical/index.md`에 항목을 추가한다.
- 기술 문서는 SRS를 source of truth로 따르며, 외부 계약이나 acceptance criteria를 재정의하지 않는다. 대신 구현 상세(모듈 책임, 파일 위치, 설정/환경값, 런타임 흐름, validation notes, open implementation points)를 정리한다.
- 문서 상단에는 반드시 `- Related REQ: ...`를 유지하거나 추가한다.
- `REQ-011`, `REQ-007`, `REQ-012`는 다음 문서를 우선 후보로 사용한다:
- `REQ-011` → `docs/technical/project-structure-baseline.md`
- `REQ-007` → `docs/technical/python-runtime-and-packaging.md`
- `REQ-012` → `docs/technical/settings-and-env-loading.md`
- `docs/technical/index.md`의 문서 목록과 연관 REQ 표도 문서 생성/연결 변경 사항에 맞게 함께 갱신한다.
- 실제 파일 변경을 수행한 뒤, 변경된 파일과 각 REQ의 승인 확인 결과를 요약한다.
출력 형식:
1. Approval Check
2. Technical Spec Updates
3. Files Changed
4. Remaining Blockers or Notes
-23
View File
@@ -1,23 +0,0 @@
name: Docs Sync Check
on:
pull_request:
jobs:
docs-sync-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Verify docs sync
run: |
python3 scripts/check_docs_sync.py --against origin/${{ github.base_ref }} --head ${{ github.sha }}
-177
View File
@@ -1,177 +0,0 @@
#!/usr/bin/env python3
"""Guardrail check for implementation-to-spec synchronization.
Rules:
- If files under app/ change, at least one docs/technical/ file must be part of the same change set.
- If files under app/api/ or app/schemas/ change, docs/technical/api-contracts.md must be part of the same change set.
- If files under migrations/versions/ change, docs/technical/persistence-and-migrations.md must be part of the same change set.
- If migrations/versions/ files change, revision IDs found in changed migration files
must appear in docs/technical/persistence-and-migrations.md.
"""
from __future__ import annotations
import argparse
import re
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
TECHNICAL_DOC_PREFIX = "docs/technical/"
DB_SPEC = "docs/technical/persistence-and-migrations.md"
API_EXAMPLES_SPEC = "docs/technical/api-contracts.md"
APP_PREFIX = "app/"
API_PREFIXES = ("app/api/", "app/schemas/")
MIGRATION_PREFIX = "migrations/versions/"
class CheckError(Exception):
pass
def _run_git(args: list[str]) -> str:
result = subprocess.run(
["git", *args],
cwd=ROOT,
check=True,
capture_output=True,
text=True,
)
return result.stdout
def _ref_exists(ref: str) -> bool:
result = subprocess.run(
["git", "rev-parse", "--verify", "--quiet", ref],
cwd=ROOT,
check=False,
capture_output=True,
text=True,
)
return result.returncode == 0
def _get_changed_files(*, staged: bool, against: str | None, head: str) -> list[str]:
if staged:
output = _run_git(["diff", "--name-only", "--cached", "--diff-filter=ACMR"])
elif against:
if not _ref_exists(against):
raise CheckError(f"base ref not found: {against}")
if not _ref_exists(head):
raise CheckError(f"head ref not found: {head}")
output = _run_git(["diff", "--name-only", "--diff-filter=ACMR", f"{against}...{head}"])
else:
if not _ref_exists("HEAD~1"):
# For a repository with a single commit, there is nothing to compare against.
return []
output = _run_git(["diff", "--name-only", "--diff-filter=ACMR", "HEAD~1", "HEAD"])
return [line.strip() for line in output.splitlines() if line.strip()]
def _extract_revision_id(path: Path) -> str | None:
text = path.read_text(encoding="utf-8")
match = re.search(r'^revision\s*=\s*["\']([^"\']+)["\']', text, flags=re.MULTILINE)
return match.group(1) if match else None
def _collect_changed_revision_ids(changed_files: list[str]) -> list[str]:
revision_ids: list[str] = []
for file in changed_files:
if not file.startswith(MIGRATION_PREFIX) or not file.endswith(".py"):
continue
migration_path = ROOT / file
if not migration_path.exists():
continue
revision_id = _extract_revision_id(migration_path)
if revision_id:
revision_ids.append(revision_id)
return revision_ids
def run_check(*, staged: bool, against: str | None, head: str) -> int:
try:
changed_files = _get_changed_files(staged=staged, against=against, head=head)
except CheckError as exc:
print(f"docs-sync-check: {exc}")
return 2
except subprocess.CalledProcessError as exc:
print("docs-sync-check: failed to read git diff")
print(exc.stderr.strip())
return 2
if not changed_files:
print("docs-sync-check: no changes detected")
return 0
needs_general_spec = any(path.startswith(APP_PREFIX) for path in changed_files)
needs_api_examples = any(path.startswith(prefix) for prefix in API_PREFIXES for path in changed_files)
needs_db_spec = any(path.startswith(MIGRATION_PREFIX) for path in changed_files)
errors: list[str] = []
if needs_general_spec and not any(path.startswith(TECHNICAL_DOC_PREFIX) for path in changed_files):
errors.append(
"Application code changed but no docs/technical/ document was updated in the same commit/PR."
)
if needs_api_examples and API_EXAMPLES_SPEC not in changed_files:
errors.append(
"API/schema code changed but docs/technical/api-contracts.md was not updated in the same commit/PR."
)
if needs_db_spec and DB_SPEC not in changed_files:
errors.append(
"Migration changed but docs/technical/persistence-and-migrations.md was not updated in the same commit/PR."
)
if needs_db_spec:
db_spec_path = ROOT / DB_SPEC
if not db_spec_path.exists():
errors.append("docs/technical/persistence-and-migrations.md is missing.")
else:
db_spec_text = db_spec_path.read_text(encoding="utf-8")
changed_revisions = _collect_changed_revision_ids(changed_files)
missing_revisions = [rev for rev in changed_revisions if rev not in db_spec_text]
if missing_revisions:
errors.append(
"Migration revision IDs missing in docs/technical/persistence-and-migrations.md: "
+ ", ".join(sorted(set(missing_revisions)))
)
if errors:
print("docs-sync-check: FAILED")
for error in errors:
print(f"- {error}")
print("\nChanged files:")
for file in changed_files:
print(f"- {file}")
return 1
print("docs-sync-check: OK")
return 0
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Verify implementation and docs stay in sync.")
parser.add_argument(
"--staged",
action="store_true",
help="Check staged files (for pre-commit).",
)
parser.add_argument(
"--against",
default=None,
help="Git base ref/sha to diff against (for CI).",
)
parser.add_argument(
"--head",
default="HEAD",
help="Git head ref/sha used with --against.",
)
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()
sys.exit(run_check(staged=args.staged, against=args.against, head=args.head))
-55
View File
@@ -1,55 +0,0 @@
# REQ-XXX: <요구사항 제목>
- Status: Proposed | Approved | Implemented | Deprecated
- Type: Interface | Data | Exception & Error Handling | Installation | Configuration | Deployment | Documentation | Integration | Testing | Non-Functional
- Priority: High | Medium | Low
- Owner: <담당자 또는 팀>
## Intent
- <이 요구사항이 필요한 이유와 달성하려는 목표를 1~3문장으로 작성>
## Requirement
- <시스템이 반드시 수행해야 하는 동작을 단정형 문장으로 작성>
## Acceptance Criteria
1. Given <선행 조건>, When <행동>, Then <기대 결과>
2. Given <선행 조건>, When <행동>, Then <기대 결과>
## Impacted Area
- Docs: <영향 받는 문서 경로>
- Modules: <영향 받는 모듈/컴포넌트>
- Tests: <추가/수정해야 하는 테스트>
## Notes
- <가정, 제약, 미해결 이슈>
## Change Log
### CHG-YYYYMMDD-01
- Date: YYYY-MM-DD
- Author: <작성자>
#### Change Summary
- <무엇이 변경되었는지>
#### Intent
- <왜 변경했는지>
#### Acceptance Criteria Delta
- Added:
- <추가된 기준>
- Updated:
- <변경된 기준>
- Removed:
- <삭제된 기준>
#### Impacted Area Delta
- Docs:
- <문서 영향>
- Modules:
- <코드 영향>
- Tests:
- <테스트 영향>
#### Validation Plan
- <검증 방법과 완료 조건>
@@ -1,28 +0,0 @@
# SRS Traceability Matrix
<!--
Usage:
1. Copy this file to docs/SRS/traceability-matrix.md in your target repository.
2. Keep one row per requirement.
3. Update Issue/PR, Test Evidence, and Status whenever implementation progresses.
-->
## Status Definition
- Planned: Requirement is defined but not yet implemented.
- In Progress: Implementation issue/PR exists and work is ongoing.
- Implemented: Code is merged and mapped acceptance criteria are complete.
- Verified: Required tests and manual checks are completed.
- Released: Included in a released version.
## Matrix
| REQ ID | AC Mapping | Requirement File | Implementation Issue | PR | Test Evidence | Requirement Status | Delivery Status | Last Updated |
|---|---|---|---|---|---|---|---|---|
| REQ-001 | AC1, AC2 | docs/SRS/<Type>/REQ-001_<slug>.md | #123 | #456 | tests/... , CI run link | Approved | Planned | YYYY-MM-DD |
## Update Rules
- REQ ID must exactly match the SRS requirement file prefix.
- AC Mapping should reference concrete IDs such as AC1, AC2.
- Test Evidence should point to executable artifacts: test file path, CI job, or manual verification note.
- Last Updated uses YYYY-MM-DD.
- If there is no value yet, use `TBD`.