From c7183d8918487c2c4002063479ef1ebd4e75f555 Mon Sep 17 00:00:00 2001 From: learncold Date: Fri, 20 Mar 2026 23:31:38 +0900 Subject: [PATCH 1/3] Github Project.md --- docs/GitHub Project.md | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 docs/GitHub Project.md diff --git a/docs/GitHub Project.md b/docs/GitHub Project.md new file mode 100644 index 0000000..af1e328 --- /dev/null +++ b/docs/GitHub Project.md @@ -0,0 +1,61 @@ +# SafeCrowd GitHub Project + +## 개요 +- Project: `SafeCrowd Implementation` +- URL: `https://github.com/users/learncold/projects/1` +- Repository: `learncold/cpp-ecs-engine` +- 관리 방식: + - Epic과 Task를 모두 issue로 관리한다. + - Epic-Task 관계는 GitHub native `Parent issue` / `sub-issue`를 사용한다. + - 선행 작업 관계는 GitHub native issue dependency `blocked by`를 사용한다. + +## 현재 필드 +- `Title` +- `Status` + - `In Progress` + - `Done` +- `Area` + - `⚙️Engine` + - `🏃Domain` + - `🖥️Application` + - `🔎Analysis` + - `📄Docs` +- `Sprint` + - `Sprint 1` + - `Sprint 2` + - `Sprint 3` + - `Later` +- `Parent issue` +- `Sub-issues progress` + +## 현재 뷰 +- 뷰 수: 1개 +- 이름: `View 1` +- 형식: `Table` +- 필터: 없음 + +권장 표시 컬럼: +- `Title` +- `Status` +- `Sprint` +- `Area` +- `Parent issue` +- `Sub-issues progress` + +## 현재 구조 +- `Sprint 1` + - Epic: `#1 EPIC-1 Engine Foundation` + - Epic: `#2 EPIC-2 Sprint 1 Demo Vertical Slice` + - Task: `#6 ~ #20` +- `Sprint 2` + - Epic: `#3 EPIC-3 Product Completion for Sprint 2` + - Epic: `#4 EPIC-4 Compare and Presentation Readiness` + - Task: `#21 ~ #30` +- `Sprint 3` + - Epic: `#5 EPIC-5 Finish and Optional Extensions` + - Task: `#31 ~ #35` + +## 메모 +- issue 본문은 `Summary`만 남기고 최소화했다. +- 세부 작업명, 부모-자식 관계, dependency는 GitHub Project와 issue 자체를 기준으로 관리한다. +- 2026-03-20 기준 현재 `In Progress` 상태인 작업은 `#6 T-001`이다. From 0f2651aaa27827e995a25ff7a20bad337bb13e74 Mon Sep 17 00:00:00 2001 From: learncold Date: Fri, 20 Mar 2026 23:49:03 +0900 Subject: [PATCH 2/3] Github Project.md --- .github/ISSUE_TEMPLATE/epic.yml | 2 + .github/ISSUE_TEMPLATE/lightweight-task.yml | 85 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/task.yml | 10 +-- AGENTS.md | 3 +- CONTRIBUTING.md | 6 +- docs/GitHub Project.md | 3 +- 6 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/lightweight-task.yml diff --git a/.github/ISSUE_TEMPLATE/epic.yml b/.github/ISSUE_TEMPLATE/epic.yml index 4384b21..0ee7b4a 100644 --- a/.github/ISSUE_TEMPLATE/epic.yml +++ b/.github/ISSUE_TEMPLATE/epic.yml @@ -7,6 +7,8 @@ body: value: | Use this form for sprint-sized work that will be broken into multiple tasks. + GitHub assigns the numeric issue number automatically. Enter only the short title after `EPIC- `. + Keep the layered architecture in mind: - `application -> domain -> engine` - `domain` must not depend on Qt UI code diff --git a/.github/ISSUE_TEMPLATE/lightweight-task.yml b/.github/ISSUE_TEMPLATE/lightweight-task.yml new file mode 100644 index 0000000..0ccc766 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/lightweight-task.yml @@ -0,0 +1,85 @@ +name: Lightweight Task +description: Create a small Docs, Chore, or Analysis task without implementation-heavy required fields. +title: "T- " +body: + - type: markdown + attributes: + value: | + Use this form for a small documentation, maintenance, or analysis task. + + GitHub assigns the numeric issue number automatically. Enter only the short title after `T- `. + Keep the issue focused enough that it can usually map to one PR. + - type: textarea + id: summary + attributes: + label: Summary + description: Describe the task in one short paragraph. + placeholder: Add a short guide for how the team should use the GitHub Project board. + validations: + required: true + - type: input + id: parent-issue + attributes: + label: Parent Issue + description: Link the parent epic when this task belongs under one. + placeholder: "#1" + - type: dropdown + id: area + attributes: + label: Area + description: Select the main area this task belongs to. + options: + - Docs + - Chore + - Analysis + validations: + required: true + - type: dropdown + id: sprint + attributes: + label: Target Sprint + description: Choose the sprint that should own this task. + options: + - Sprint 1 + - Sprint 2 + - Sprint 3 + - Later + validations: + required: true + - type: textarea + id: deliverable + attributes: + label: Deliverable + description: State what concrete output or change should exist when the task is done. + placeholder: | + - Add `docs/GitHub Project.md` + - Capture the expected team workflow + validations: + required: true + - type: textarea + id: done-when + attributes: + label: Done When + description: List the simplest completion criteria for this task. + placeholder: | + - The document or maintenance change is merged + - The intended audience can use the result without extra clarification + validations: + required: true + - type: textarea + id: verification + attributes: + label: Verification / Notes + description: Record how the task should be checked, or explain why no build/test validation is needed. + placeholder: | + - Review the markdown in GitHub + - Docs-only change; no build/test run required + - type: checkboxes + id: checks + attributes: + label: Repository Checks + options: + - label: I checked for an existing related issue or epic before creating this task. + required: true + - label: I will keep the issue title aligned with the repository naming convention. + required: true diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml index 56ba35d..00f058a 100644 --- a/.github/ISSUE_TEMPLATE/task.yml +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -1,12 +1,13 @@ -name: Task -description: Create a single implementation, analysis, docs, or maintenance task. +name: Implementation Task +description: Create a scoped code or build task for Engine, Domain, Application, or Build work. title: "T- " body: - type: markdown attributes: value: | - Use this form for a single unit of work. + Use this form for a single implementation or build task. + GitHub assigns the numeric issue number automatically. Enter only the short title after `T- `. Prefer one task per PR, and keep the task scoped tightly enough that it can be reviewed and merged independently. - type: textarea id: summary @@ -31,10 +32,7 @@ body: - Engine - Domain - Application - - Docs - Build - - Analysis - - Chore validations: required: true - type: dropdown diff --git a/AGENTS.md b/AGENTS.md index bedead8..806c5d7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -55,7 +55,8 @@ - Use GitHub issue forms for new work items; blank issues are disabled. - Issue types currently supported: - `Epic` for larger parent work - - `Task` for single implementation/analysis/docs work + - `Implementation Task` for `Engine` / `Domain` / `Application` / `Build` work + - `Lightweight Task` for `Docs` / `Chore` / `Analysis` work - GitHub Project guidance is documented in `docs/GitHub Project.md`. - PR titles must follow `[Area] short summary`. - Allowed PR areas: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0dfbb92..401730c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,8 +14,10 @@ PR은 작은 단위로 나누고, 어떤 issue를 해결하는지 분명하게 - 새 work item은 GitHub issue form으로 생성합니다. - `Epic`은 여러 task를 묶는 상위 계획에 사용합니다. -- `Task`는 구현, 분석, 문서화 같은 단일 작업 단위에 사용합니다. -- 제목은 저장소 관례에 맞춰 `EPIC-n short title` 또는 `T-xxx short title` 형식을 유지합니다. +- `Implementation Task`는 `Engine`, `Domain`, `Application`, `Build` 같은 코드/빌드 작업에 사용합니다. +- `Lightweight Task`는 `Docs`, `Chore`, `Analysis` 같은 작은 작업에 사용합니다. +- 제목은 저장소 관례에 맞춰 `EPIC- short title` 또는 `T- short title` 형식을 유지합니다. +- GitHub issue 번호(`#12` 같은 값)는 생성 후 자동으로 붙습니다. 제목에는 숫자를 직접 적지 않습니다. - 가능하면 task는 parent epic을 함께 적고, Sprint와 Area를 바로 정합니다. - 구조나 의존성에 영향을 주는 issue는 본문에 계층 영향과 검증 계획을 남깁니다. diff --git a/docs/GitHub Project.md b/docs/GitHub Project.md index af1e328..ac34db4 100644 --- a/docs/GitHub Project.md +++ b/docs/GitHub Project.md @@ -56,6 +56,7 @@ - Task: `#31 ~ #35` ## 메모 -- issue 본문은 `Summary`만 남기고 최소화했다. +- `Docs`, `Chore`, `Analysis`는 `Lightweight Task` form으로 가볍게 등록한다. +- `Engine`, `Domain`, `Application`, `Build`는 `Implementation Task` form으로 범위와 검증 계획까지 남긴다. - 세부 작업명, 부모-자식 관계, dependency는 GitHub Project와 issue 자체를 기준으로 관리한다. - 2026-03-20 기준 현재 `In Progress` 상태인 작업은 `#6 T-001`이다. From df08b0400ceb26527858ca41ba75bf51faae6d98 Mon Sep 17 00:00:00 2001 From: learncold Date: Sat, 21 Mar 2026 03:15:02 +0900 Subject: [PATCH 3/3] [Docs] allow docs-only PRs without issues and rename Task prefix --- .github/ISSUE_TEMPLATE/lightweight-task.yml | 4 +-- .github/ISSUE_TEMPLATE/task.yml | 4 +-- .github/PULL_REQUEST_TEMPLATE.md | 1 + .github/workflows/pr-policy.yml | 37 +++++++++++++++++++-- CONTRIBUTING.md | 7 ++-- docs/GitHub Project.md | 20 ++++++----- 6 files changed, 54 insertions(+), 19 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/lightweight-task.yml b/.github/ISSUE_TEMPLATE/lightweight-task.yml index 0ccc766..0f1d6a2 100644 --- a/.github/ISSUE_TEMPLATE/lightweight-task.yml +++ b/.github/ISSUE_TEMPLATE/lightweight-task.yml @@ -1,13 +1,13 @@ name: Lightweight Task description: Create a small Docs, Chore, or Analysis task without implementation-heavy required fields. -title: "T- " +title: "Task- " body: - type: markdown attributes: value: | Use this form for a small documentation, maintenance, or analysis task. - GitHub assigns the numeric issue number automatically. Enter only the short title after `T- `. + GitHub assigns the numeric issue number automatically. Enter only the short title after `Task- `. Keep the issue focused enough that it can usually map to one PR. - type: textarea id: summary diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml index 00f058a..b3aaf63 100644 --- a/.github/ISSUE_TEMPLATE/task.yml +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -1,13 +1,13 @@ name: Implementation Task description: Create a scoped code or build task for Engine, Domain, Application, or Build work. -title: "T- " +title: "Task- " body: - type: markdown attributes: value: | Use this form for a single implementation or build task. - GitHub assigns the numeric issue number automatically. Enter only the short title after `T- `. + GitHub assigns the numeric issue number automatically. Enter only the short title after `Task- `. Prefer one task per PR, and keep the task scoped tightly enough that it can be reviewed and merged independently. - type: textarea id: summary diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 95ee47c..cb1639c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,6 +5,7 @@ ## Related Issue - Closes # +- None (docs/policy-only PR) ## Area diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml index 3caee93..a4058fe 100644 --- a/.github/workflows/pr-policy.yml +++ b/.github/workflows/pr-policy.yml @@ -56,13 +56,44 @@ jobs: const relatedIssueSection = section("## Related Issue"); const areaSection = section("## Area"); const verificationSection = section("## Verification"); + const selectedAreas = [...areaSection.matchAll(/- \[[xX]\] (.+)/g)].map((match) => match[1].trim()); + const noIssuePattern = /\b(?:none|n\/a|no separate issue)\b/i; + + const changedFiles = await github.paginate(github.rest.pulls.listFiles, { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + per_page: 100, + }); + + const docsPolicyOnlyPatterns = [ + /^docs\//, + /^uml\//, + /^\.github\/ISSUE_TEMPLATE\//, + /^\.github\/PULL_REQUEST_TEMPLATE\.md$/, + /^\.github\/workflows\/pr-policy\.yml$/, + /^CONTRIBUTING\.md$/, + /^README\.md$/, + ]; + + const isDocsPolicyOnlyPr = + changedFiles.length > 0 && + changedFiles.every((file) => + docsPolicyOnlyPatterns.some((pattern) => pattern.test(file.filename)) + ); + const isDocsAreaOnly = selectedAreas.length === 1 && selectedAreas[0] === "Docs"; const issuePattern = /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?|refs?)\s+#\d+\b/i; - if (!issuePattern.test(relatedIssueSection)) { - errors.push("`## Related Issue` must include an issue reference such as `Closes #12`."); + const hasIssueReference = issuePattern.test(relatedIssueSection); + const usesDocsOnlyException = noIssuePattern.test(relatedIssueSection); + + if (!hasIssueReference) { + if (!(usesDocsOnlyException && isDocsAreaOnly && isDocsPolicyOnlyPr)) { + errors.push("`## Related Issue` must include an issue reference such as `Closes #12`, unless this is a Docs-only docs/policy PR and the section says `None (docs/policy-only PR)`."); + } } - if (!/- \[[xX]\] /.test(areaSection)) { + if (selectedAreas.length === 0) { errors.push("Select at least one checkbox in `## Area`."); } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 401730c..ada8d56 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,12 @@ # SafeCrowd Contribution Rules 이 저장소는 `application -> domain -> engine` 계층을 유지하는 것을 가장 중요한 규칙으로 둡니다. -PR은 작은 단위로 나누고, 어떤 issue를 해결하는지 분명하게 남겨 주세요. +PR은 작은 단위로 나누고, 기본적으로 어떤 issue를 해결하는지 분명하게 남겨 주세요. ## 기본 원칙 - 기본 작업 흐름은 `issue -> branch -> PR -> merge`입니다. +- 다만 `docs/`, `uml/`, `CONTRIBUTING.md`, PR/issue template, PR 정책 워크플로처럼 문서 또는 기여 정책만 다루는 변경은 별도 issue 없이 `branch -> PR -> merge`로 진행할 수 있습니다. - 가능하면 하나의 PR은 하나의 issue만 해결합니다. - 서로 다른 계층을 동시에 크게 건드리는 PR은 피합니다. - 구조, 빌드, 의존성 규칙이 바뀌면 관련 문서를 함께 업데이트합니다. @@ -16,7 +17,7 @@ PR은 작은 단위로 나누고, 어떤 issue를 해결하는지 분명하게 - `Epic`은 여러 task를 묶는 상위 계획에 사용합니다. - `Implementation Task`는 `Engine`, `Domain`, `Application`, `Build` 같은 코드/빌드 작업에 사용합니다. - `Lightweight Task`는 `Docs`, `Chore`, `Analysis` 같은 작은 작업에 사용합니다. -- 제목은 저장소 관례에 맞춰 `EPIC- short title` 또는 `T- short title` 형식을 유지합니다. +- 제목은 저장소 관례에 맞춰 `EPIC- short title` 또는 `Task- short title` 형식을 유지합니다. - GitHub issue 번호(`#12` 같은 값)는 생성 후 자동으로 붙습니다. 제목에는 숫자를 직접 적지 않습니다. - 가능하면 task는 parent epic을 함께 적고, Sprint와 Area를 바로 정합니다. - 구조나 의존성에 영향을 주는 issue는 본문에 계층 영향과 검증 계획을 남깁니다. @@ -51,7 +52,7 @@ PR 제목은 아래 형식을 따릅니다. 모든 PR은 아래 내용을 포함해야 합니다. - 변경 요약 -- 연결된 issue +- 연결된 issue 또는 docs/policy-only PR 예외 사유 - 변경이 속한 영역 - 아키텍처 규칙 점검 결과 - 빌드/테스트 검증 결과 또는 미실행 사유 diff --git a/docs/GitHub Project.md b/docs/GitHub Project.md index ac34db4..f5e8991 100644 --- a/docs/GitHub Project.md +++ b/docs/GitHub Project.md @@ -8,6 +8,7 @@ - Epic과 Task를 모두 issue로 관리한다. - Epic-Task 관계는 GitHub native `Parent issue` / `sub-issue`를 사용한다. - 선행 작업 관계는 GitHub native issue dependency `blocked by`를 사용한다. + - Task 제목은 `Task- short title` 형식을 사용하고, 순서는 제목 번호가 아니라 GitHub issue 번호, Sprint, Parent issue, dependency로 관리한다. ## 현재 필드 - `Title` @@ -44,19 +45,20 @@ ## 현재 구조 - `Sprint 1` - - Epic: `#1 EPIC-1 Engine Foundation` - - Epic: `#2 EPIC-2 Sprint 1 Demo Vertical Slice` - - Task: `#6 ~ #20` + - Epic: `#1 EPIC- Engine Foundation` + - Epic: `#2 EPIC- Sprint 1 Demo Vertical Slice` + - Task: 각 epic 아래 `Task- ...` sub-issue로 관리 - `Sprint 2` - - Epic: `#3 EPIC-3 Product Completion for Sprint 2` - - Epic: `#4 EPIC-4 Compare and Presentation Readiness` - - Task: `#21 ~ #30` + - Epic: `#3 EPIC- Product Completion for Sprint 2` + - Epic: `#4 EPIC- Compare and Presentation Readiness` + - Task: 각 epic 아래 `Task- ...` sub-issue로 관리 - `Sprint 3` - - Epic: `#5 EPIC-5 Finish and Optional Extensions` - - Task: `#31 ~ #35` + - Epic: `#5 EPIC- Finish and Optional Extensions` + - Task: 각 epic 아래 `Task- ...` sub-issue로 관리 ## 메모 - `Docs`, `Chore`, `Analysis`는 `Lightweight Task` form으로 가볍게 등록한다. - `Engine`, `Domain`, `Application`, `Build`는 `Implementation Task` form으로 범위와 검증 계획까지 남긴다. - 세부 작업명, 부모-자식 관계, dependency는 GitHub Project와 issue 자체를 기준으로 관리한다. -- 2026-03-20 기준 현재 `In Progress` 상태인 작업은 `#6 T-001`이다. +- 문서 또는 기여 정책만 다루는 PR은 별도 issue 없이 진행할 수 있다. +- Task의 순서는 제목 접두사 뒤 숫자로 관리하지 않는다. 중간 작업이 생기면 새 issue를 추가하고 `Sprint`, `Parent issue`, `blocked by`로 위치를 표현한다.