Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
383 changes: 180 additions & 203 deletions .claude/agents/qa-engineer.md

Large diffs are not rendered by default.

143 changes: 137 additions & 6 deletions .claude/agents/verifier.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,18 +147,149 @@ grep -r "import.*from" src/ --include="*.ts" | head -20

## 驗證結果處理

### PASS(全部通過)
```bash
gh issue comment {sprint_issue} --body "✅ Sprint {N} 三維度驗證通過,可以 release"
```
### PASS / WARNING(通過或輕微問題)

驗證通過後,**自動產出 Sprint 工作日誌**:

### WARNING(有輕微問題)
```bash
gh issue comment {sprint_issue} --body "🟡 Sprint {N} 驗證有 warnings,建議修復但不阻塞 release。詳見 specs/verify-sprint-{N}.md"
gh issue comment {sprint_issue} --body " Sprint {N} 三維度驗證通過"
```

接著執行「Sprint 工作日誌」流程(見下方)。

### FAIL(有嚴重問題)
建立 bug issue 並通知:
```bash
gh issue comment {sprint_issue} --body "🔴 Sprint {N} 驗證失敗,需修復後重新驗證。詳見 specs/verify-sprint-{N}.md"
```

---

## Sprint 工作日誌

驗證通過後(PASS 或 WARNING),自動產出 Sprint 工作日誌到 `specs/logs/sprint-{N}-log.md`。

### 日誌格式

```markdown
# Sprint {N} 工作日誌

## 基本資訊

| 項目 | 內容 |
|------|------|
| **Sprint** | Sprint {N} |
| **Milestone** | [Sprint {N}]({milestone_url}) |
| **日期** | {start_date} ~ {end_date} |
| **Epic** | [#{epic_number}]({epic_url}) |
| **Sprint Issue** | [#{sprint_issue_number}]({sprint_issue_url}) |

## 完成功能

### F-{NNN}: {功能名稱}
- **Issue**: [#{number}]({issue_url})
- **PR**: [#{pr_number}]({pr_url})
- **Branch**: `feature/{N}-{name}`
- **Scenarios**: {passed}/{total} 通過

> {功能簡述,1-2 句話}

(每個 feature 重複此區塊)

## UI 設計

| 項目 | 內容 |
|------|------|
| **Design Issue** | [#{number}]({issue_url}) |
| **PR** | [#{pr_number}]({pr_url}) |
| **元件數量** | {N} 個 |

交付元件:
- {Component 1}
- {Component 2}

(無 UI 設計時省略此區塊)

## 測試結果

| 測試類型 | 通過 | 失敗 | 結果 |
|----------|------|------|------|
| Unit Tests | {N} | {N} | ✅/❌ |
| API E2E Tests | {N} | {N} | ✅/❌ |
| Browser Tests (Playwright) | {N} | {N} | ✅/❌ |

- **QA Issue**: [#{number}]({issue_url})
- **Test PR**: [#{pr_number}]({pr_url})
- **Test Report**: [`test/reports/sprint-{N}-test-report.md`]({link})

## Bug 修復

| Bug | Issue | Fix PR | 描述 | 嚴重度 |
|-----|-------|--------|------|--------|
| #{number} | [#{number}]({url}) | [#{pr}]({url}) | {description} | {severity} |

(無 bug 時顯示「本 sprint 無 bug」)

## 三維度驗證

| 維度 | 結果 | 詳情 |
|------|------|------|
| Completeness | ✅/❌ | {summary} |
| Correctness | ✅/❌ | {summary} |
| Coherence | ✅/❌ | {summary} |

- **驗證報告**: [`specs/verify-sprint-{N}.md`]({link})

## 數據摘要

| 指標 | 數量 |
|------|------|
| Feature Issues | {N} |
| Pull Requests | {N} |
| Commits | {N} |
| Bug 修復 | {N} |
| 測試 Scenarios | {N} |

## 所有相關 PR

| PR | 標題 | 狀態 |
|----|------|------|
| [#{number}]({url}) | {title} | ✅ Merged |

---
*Generated by SpecFlow — {timestamp}*
```

### 產出流程

```bash
mkdir -p specs/logs
SPRINT="{current_sprint}"
SPRINT_NUM={N}

# 收集資料(透過 GitHub API)
MILESTONE_URL=$(gh api repos/{owner}/{repo}/milestones --jq '.[] | select(.title=="'"$SPRINT"'") | .html_url')
FEATURES=$(gh issue list --label "feature" --milestone "$SPRINT" --state closed --json number,title,url)
BUGS=$(gh issue list --label "bug" --milestone "$SPRINT" --state closed --json number,title,url)
PRS=$(gh pr list --state merged --search "milestone:\"$SPRINT\"" --json number,title,url,mergedAt)

# 產出日誌(使用上述格式)
# 寫入 specs/logs/sprint-{N}-log.md

# Commit
git add specs/logs/
git commit -m "docs: sprint ${SPRINT_NUM} work log

Refs #{sprint_issue_number}"
git push

# 在 Sprint issue 留言
gh issue comment {sprint_issue} --body "📋 工作日誌:specs/logs/sprint-${SPRINT_NUM}-log.md"
```

### 日誌要求

1. **所有連結都要可點擊**:issue 和 PR 都附完整 URL
2. **格式嚴格一致**:每個 sprint 的日誌結構完全相同
3. **資料從 GitHub API 取得**:不依賴本地狀態
4. **Commit 到 repo**:日誌是 repo 的一部分
2 changes: 1 addition & 1 deletion .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"Bash(jq *)",
"Bash(sort *)",
"Bash(brew *)",
"Bash(agent-browser *)",
"Bash(npx playwright *)",
"Bash(rm /tmp/*)",
"Bash(rm -r /tmp/*)",
"Bash(rm -rf /tmp/*)"
Expand Down
170 changes: 80 additions & 90 deletions .claude/skills/specflow:release/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,147 +1,137 @@
---
name: specflow:release
description: 確認當前 sprint release,關閉 milestone,自動推進到下一個 sprint。必須 QA 完整測試通過才能 release。觸發關鍵字:"release", "發佈", "上線"。
description: 部署 production。所有 sprint 完成後(或使用者決定部署時),執行 production 部署流程。觸發關鍵字:"release", "發佈", "上線", "deploy", "部署"。
user-invocable: true
allowed-tools: Read, Bash, Agent
argument-hint: "[sprint編號]"
argument-hint: "[版本號]"
---

# Sprint Release 確認
# Production 部署確認

確認當前 sprint 的交付成果,關閉 milestone,自動推進下一個 sprint
**QA 完整測試必須通過才能 release。**
當所有 sprint 開發完成(或使用者決定部署當前進度),執行 production 部署
**Sprint 之間的推進是自動的,不需要手動 release。**

## 流程

### 第一步:Release 前置檢查(Gate)
### 第一步:部署前置檢查(Gate)

**以下條件全部通過才能 release,任一未通過則阻擋:**
**以下條件全部通過才能部署,任一未通過則阻擋:**

```bash
SPRINT="{current_sprint}"
BLOCK=false

# 1. QA issue 必須已關閉(代表完整測試通過)
OPEN_QA=$(gh issue list --label "qa" --milestone "$SPRINT" --state open --json number --jq 'length')
if [ "$OPEN_QA" -gt 0 ]; then
echo "❌ BLOCKED: QA issue 尚未關閉(完整測試未通過)"
BLOCK=true
fi

# 2. 所有 feature issues 必須已關閉
OPEN_FEATURES=$(gh issue list --label "feature" --milestone "$SPRINT" --state open --json number --jq 'length')
if [ "$OPEN_FEATURES" -gt 0 ]; then
echo "❌ BLOCKED: 有 $OPEN_FEATURES 個 feature issue 未關閉"
BLOCK=true
# 1. 確認沒有進行中的 sprint(所有 sprint milestone 已關閉)
OPEN_SPRINTS=$(gh api repos/{owner}/{repo}/milestones?state=open --jq '[.[] | select(.title | startswith("Sprint"))] | length')
if [ "$OPEN_SPRINTS" -gt 0 ]; then
echo "⚠️ 警告: 有 $OPEN_SPRINTS 個 sprint 尚未完成"
echo "(可繼續部署已完成的部分,或等待全部完成)"
fi

# 3. 所有 bug issues 必須已關閉
OPEN_BUGS=$(gh issue list --label "bug" --milestone "$SPRINT" --state open --json number --jq 'length')
# 2. 所有已關閉 sprint 的 test report 必須 ALL PASSED
for report in test/reports/sprint-*-test-report.md; do
[ -f "$report" ] || continue
if ! grep -q "ALL TESTS PASSED" "$report"; then
Comment on lines +31 to +33
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Block deployment when no test reports are found

The release gate now iterates over test/reports/sprint-*-test-report.md but immediately continues when files are missing, so BLOCK remains false when there are zero reports. In that case deployment can proceed without any sprint test evidence, which violates the stated gate requirement that all sprint reports must be ALL TESTS PASSED (the same missing-file pattern is also used for verify reports).

Useful? React with 👍 / 👎.

echo "❌ BLOCKED: $report 顯示有失敗的測試"
BLOCK=true
fi
done

# 3. 所有驗證報告必須為 PASS
for verify in specs/verify-sprint-*.md; do
[ -f "$verify" ] || continue
if grep -q "🔴 FAIL" "$verify"; then
echo "❌ BLOCKED: $verify 驗證失敗"
BLOCK=true
fi
done

# 4. 沒有 open 的 bug issues
OPEN_BUGS=$(gh issue list --label "bug" --state open --json number --jq 'length')
if [ "$OPEN_BUGS" -gt 0 ]; then
echo "❌ BLOCKED: 有 $OPEN_BUGS 個 bug issue 未關閉"
echo "❌ BLOCKED: 有 $OPEN_BUGS 個 bug issue 未修復"
BLOCK=true
fi

# 4. 所有 PR 必須已合併
# 5. main 分支沒有未合併的 PR
OPEN_PRS=$(gh pr list --state open --json headRefName --jq '[.[] | select(.headRefName | startswith("feature/") or startswith("fix/") or startswith("test/"))] | length')
if [ "$OPEN_PRS" -gt 0 ]; then
echo "❌ BLOCKED: 有 $OPEN_PRS 個 PR 未合併"
BLOCK=true
fi

# 5. Test Report 必須存在且為 ALL PASSED
if [ ! -f "test/reports/sprint-{N}-test-report.md" ]; then
echo "❌ BLOCKED: Test Report 不存在(QA 尚未執行完整測試)"
BLOCK=true
elif ! grep -q "ALL TESTS PASSED" "test/reports/sprint-{N}-test-report.md"; then
echo "❌ BLOCKED: Test Report 顯示有失敗的測試"
BLOCK=true
fi

# 6. 驗證報告必須存在且為 PASS
if [ ! -f "specs/verify-sprint-{N}.md" ]; then
echo "❌ BLOCKED: 驗證報告不存在(請先執行 /specflow:verify)"
BLOCK=true
fi
```

如果 `BLOCK=true`,列出所有阻擋項目,**不執行 release**。
提示使用者需要先解決阻擋項目。
如果 `BLOCK=true`,列出所有阻擋項目,**不執行部署**。

### 第二步:產出 Release 總報告

### 第二步:產出 Sprint 報告
彙整所有 sprint 的工作日誌,產出完整的 release 報告:

```bash
gh issue comment {epic_number} --body "$(cat <<'BODY'
## 🚀 Sprint {N} Released

### 交付功能
- #{feature} F-001: {名稱} ✅
- #{feature} F-002: {名稱} ✅

### 完整測試結果
| 測試類型 | 結果 |
|----------|------|
| Unit Tests | ✅ passed |
| API E2E Tests | ✅ passed |
| Browser Tests | ✅ passed |
| 三維度驗證 | ✅ PASS |

### 數據摘要
| 項目 | 數量 |
|------|------|
| Feature Issues | X |
| Pull Requests | X |
| Bugs 修復 | X |

### PRs
- #{pr} {title}
## 🚀 Production Release

### 完成的 Sprint
(列出所有已完成的 sprint 及其工作日誌連結)

### 交付功能總覽
(從各 sprint 工作日誌彙整)

### 測試結果
所有 sprint 測試均 ✅ PASS
所有 sprint 驗證均 ✅ PASS

### 工作日誌
(列出所有 `specs/logs/sprint-{N}-log.md` 連結)
BODY
)"
```

### 第三步:關閉 Sprint Milestone
### 第三步:建立 Release Tag

```bash
MILESTONE_NUMBER=$(gh api repos/{owner}/{repo}/milestones --jq '.[] | select(.title | startswith("Sprint {N}")) | .number')
gh api repos/{owner}/{repo}/milestones/$MILESTONE_NUMBER -X PATCH -f state="closed"
```
VERSION="${ARGUMENTS:-v1.0.0}"
git tag -a "$VERSION" -m "Release $VERSION"
git push origin "$VERSION"

### 第四步:關閉 Sprint Issue
# 建立 GitHub Release
gh release create "$VERSION" \
--title "Release $VERSION" \
--notes "$(cat <<'NOTES'
## Release $VERSION

```bash
gh issue close {sprint_issue_number} --reason completed
```
### 包含的 Sprint
(列出所有 sprint)

### 第五步:自動推進下一個 Sprint
### 主要功能
(從工作日誌彙整)

```bash
NEXT_SPRINT=$(gh api repos/{owner}/{repo}/milestones --jq '[.[] | select(.state=="open") | select(.title | startswith("Sprint"))] | sort_by(.title) | .[0].title')
### 工作日誌
(連結到 specs/logs/)
NOTES
)"
```

如果有下一個 sprint:
1. 通知使用者:「Sprint {N} 已 release,自動推進到 {next_sprint}」
2. 自動啟動 tech-lead → (engineer + qa 並行) 的背景流程
### 第四步:關閉 Epic Issue

如果沒有下一個 sprint:
1. 通知使用者:「所有 sprint 已完成!專案交付完畢。」
```bash
gh issue close {epic_number} --reason completed
```

## Release Gate 總結
## 部署 Gate 總結

| # | 檢查項目 | 必須 | 來源 |
|---|----------|------|------|
| 1 | QA issue 已關閉 | ✅ | QA 完整測試通過後才會關閉 |
| 2 | 所有 feature issues 已關閉 | ✅ | PR merge 自動關閉 |
| 3 | 所有 bug issues 已關閉 | ✅ | fix PR merge 自動關閉 |
| 4 | 所有 PR 已合併 | ✅ | engineer + qa + design 的 PR |
| 5 | Test Report ALL PASSED | ✅ | `test/reports/sprint-{N}-test-report.md` |
| 6 | 驗證報告 PASS | ✅ | verifier 三維度檢查 |
| 1 | Test Report ALL PASSED | ✅ | 各 sprint 的 `test/reports/` |
| 2 | 驗證報告 PASS | ✅ | 各 sprint 的 `specs/verify-sprint-{N}.md` |
| 3 | 無 open bugs | ✅ | GitHub Issues |
| 4 | 所有 PR 已合併 | ✅ | GitHub PRs |

**缺任何一項都不能 release。**
**缺任何一項都不能部署。**

Test Report 包含:
- Docker Compose 環境狀態
- Unit Tests 結果
- API E2E Tests 結果
- Browser Tests 結果(agent-browser
- Browser Tests 結果(Playwright
- Scenario 覆蓋率
- 發現的問題清單
Loading