spec-runner 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -188
- package/bin/spec-runner.js +192 -706
- package/install.sh +6 -12
- package/package.json +3 -2
- package/templates/.spec-runner/hooks/pre-commit +33 -0
- package/templates/.spec-runner/hooks/pre-push +9 -0
- package/templates/.spec-runner/project.json.example +25 -0
- package/templates/.spec-runner/scripts/branch/create-uc-branch.sh +105 -0
- package/templates/.spec-runner/scripts/branch/uc-next-id.sh +17 -0
- package/templates/.spec-runner/scripts/branch/uc-next-start.sh +81 -0
- package/templates/.spec-runner/scripts/check/drift.sh +66 -0
- package/templates/.spec-runner/scripts/check/health.sh +103 -0
- package/templates/.spec-runner/scripts/check/naming.sh +51 -0
- package/templates/.spec-runner/scripts/check/schema-drift.sh +74 -0
- package/templates/.spec-runner/scripts/check/schema-sync.sh +153 -0
- package/templates/.spec-runner/scripts/check.sh +20 -0
- package/templates/.spec-runner/scripts/lib/uc-context.sh +75 -0
- package/templates/.spec-runner/scripts/openapi/openapi-generate.sh +207 -0
- package/templates/.spec-runner/scripts/setup/init-project.sh +152 -0
- package/templates/.spec-runner/scripts/spec-runner-core.sh +282 -0
- package/templates/.spec-runner/scripts/test/require-tests-green.sh +83 -0
- package/templates/.spec-runner/spec-runner.sh +30 -0
- package/templates/.spec-runner/steps//343/201/235/343/201/256/344/273/226/344/275/234/346/245/255.md +22 -0
- package/templates/.spec-runner/steps//343/202/277/343/202/271/343/202/257/344/270/200/350/246/247.md +132 -0
- package/templates/.spec-runner/steps//343/203/201/343/202/247/343/203/203/343/202/257/343/203/252/343/202/271/343/203/210.md +106 -0
- package/templates/.spec-runner/steps//343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +50 -0
- package/templates/.spec-runner/steps//343/203/211/343/203/241/343/202/244/343/203/263/350/250/255/350/250/210.md +32 -0
- package/templates/.spec-runner/steps//344/273/225/346/247/230/347/255/226/345/256/232.md +219 -0
- package/templates/.spec-runner/steps//345/210/206/346/236/220.md +167 -0
- package/templates/.spec-runner/steps//345/256/237/350/243/205.md +91 -0
- package/templates/.spec-runner/steps//345/256/237/350/243/205/350/250/210/347/224/273.md +96 -0
- package/templates/.spec-runner/steps//346/206/262/347/253/240.md +74 -0
- package/templates/.spec-runner/steps//346/233/226/346/230/247/343/201/225/350/247/243/346/266/210.md +159 -0
- package/templates/.spec-runner/templates/UC-NNN-/343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271/345/220/215.md +22 -0
- package/templates/spec-runner-command.md +42 -0
- package/templates/base/.github/PULL_REQUEST_TEMPLATE.md +0 -43
- package/templates/base/.github/workflows/phase-gate-check.yml +0 -216
- package/templates/base/scripts/spec-runner.sh +0 -1144
- package/templates/base/templates/01_/350/246/201/344/273/266/345/256/232/347/276/251//343/201/262/343/201/252/345/275/242.md +0 -40
- package/templates/base/templates/03_/350/251/263/347/264/260/350/250/255/350/250/210//343/202/244/343/203/263/343/203/225/343/203/251.md +0 -14
- package/templates/base/templates/03_/350/251/263/347/264/260/350/250/255/350/250/210//343/203/206/343/203/274/343/203/226/343/203/253.md +0 -17
- package/templates/base/templates/03_/350/251/263/347/264/260/350/250/255/350/250/210//343/203/211/343/203/241/343/202/244/343/203/263.md +0 -18
- package/templates/base/templates/03_/350/251/263/347/264/260/350/250/255/350/250/210//343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271.md +0 -12
- package/templates/base/templates/99_/350/250/255/350/250/210/345/210/244/346/226/255/350/250/230/351/214/262//343/201/262/343/201/252/345/275/242.md +0 -46
- package/templates/base/templates/README.md +0 -32
- package/templates/base/templates//345/210/235/346/234/237/343/203/211/343/202/255/343/203/245/343/203/241/343/203/263/343/203/210/01_/346/206/262/347/253/240.md +0 -48
- package/templates/base/templates//345/210/235/346/234/237/343/203/211/343/202/255/343/203/245/343/203/241/343/203/263/343/203/210/02_/344/273/225/346/247/230.md +0 -39
- package/templates/base/templates//345/210/235/346/234/237/343/203/211/343/202/255/343/203/245/343/203/241/343/203/263/343/203/210/03_/347/224/250/350/252/236/351/233/206.md +0 -51
- package/templates/base/templates//345/210/235/346/234/237/343/203/211/343/202/255/343/203/245/343/203/241/343/203/263/343/203/210/99_/350/250/255/350/250/210/345/210/244/346/226/255/350/250/230/351/214/262/.gitkeep +0 -0
- package/templates/base/templates//345/210/235/346/234/237/343/203/211/343/202/255/343/203/245/343/203/241/343/203/263/343/203/210//343/203/206/343/203/263/343/203/227/343/203/254/343/203/274/343/203/210/344/270/200/350/246/247.md +0 -14
- package/templates/base/templates//345/210/235/346/234/237/343/203/211/343/202/255/343/203/245/343/203/241/343/203/263/343/203/210//346/214/257/343/202/212/350/277/224/343/202/212//350/262/240/345/202/265.md +0 -8
- package/templates/claude/.claude/commands/sr-/343/202/262/343/203/274/343/203/210/350/250/255/345/256/232.md +0 -9
- package/templates/claude/.claude/commands/sr-/343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +0 -9
- package/templates/claude/.claude/commands/sr-/343/203/254/343/203/223/343/203/245/343/203/274.md +0 -9
- package/templates/claude/.claude/commands/sr-/344/273/225/346/247/230.md +0 -9
- package/templates/claude/.claude/commands/sr-/344/277/256/346/255/243.md +0 -9
- package/templates/claude/.claude/commands/sr-/345/210/235/346/234/237/345/214/226.md +0 -10
- package/templates/claude/.claude/commands/sr-/345/256/237/350/243/205.md +0 -9
- package/templates/claude/.claude/commands/sr-/346/206/262/347/253/240.md +0 -9
- package/templates/claude/.claude/commands/sr-/346/246/202/350/246/201/350/250/255/350/250/210.md +0 -9
- package/templates/claude/.claude/commands/sr-/347/212/266/346/205/213.md +0 -9
- package/templates/claude/.claude/commands/sr-/347/267/212/346/200/245/344/277/256/346/255/243.md +0 -9
- package/templates/claude/.claude/commands/sr-/350/250/255/345/256/232.md +0 -11
- package/templates/claude/.claude/commands/sr-/350/251/263/347/264/260/350/250/255/350/250/210.md +0 -9
- package/templates/claude/.claude/hooks/pre-tool-use.sh +0 -79
- package/templates/claude/.claude/settings.json +0 -29
- package/templates/claude/CLAUDE.md +0 -141
- package/templates/copilot/.github/copilot-instructions.md +0 -25
- package/templates/copilot/.github/prompts/sr-/343/202/262/343/203/274/343/203/210/350/250/255/345/256/232.prompt.md +0 -14
- package/templates/copilot/.github/prompts/sr-/343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/343/203/254/343/203/223/343/203/245/343/203/274.prompt.md +0 -14
- package/templates/copilot/.github/prompts/sr-/344/273/225/346/247/230.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/344/277/256/346/255/243.prompt.md +0 -14
- package/templates/copilot/.github/prompts/sr-/345/210/235/346/234/237/345/214/226.prompt.md +0 -15
- package/templates/copilot/.github/prompts/sr-/345/256/237/350/243/205.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/346/206/262/347/253/240.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/346/246/202/350/246/201/350/250/255/350/250/210.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/347/212/266/346/205/213.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/347/267/212/346/200/245/344/277/256/346/255/243.prompt.md +0 -14
- package/templates/copilot/.github/prompts/sr-/350/250/255/345/256/232.prompt.md +0 -13
- package/templates/copilot/.github/prompts/sr-/350/251/263/347/264/260/350/250/255/350/250/210.prompt.md +0 -14
- package/templates/cursor/.cursor/commands/sr-/343/202/262/343/203/274/343/203/210/350/250/255/345/256/232.md +0 -11
- package/templates/cursor/.cursor/commands/sr-/343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/343/203/254/343/203/223/343/203/245/343/203/274.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/344/273/225/346/247/230.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/344/277/256/346/255/243.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/345/210/235/346/234/237/345/214/226.md +0 -35
- package/templates/cursor/.cursor/commands/sr-/345/256/237/350/243/205.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/346/206/262/347/253/240.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/346/246/202/350/246/201/350/250/255/350/250/210.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/347/212/266/346/205/213.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/347/267/212/346/200/245/344/277/256/346/255/243.md +0 -9
- package/templates/cursor/.cursor/commands/sr-/350/250/255/345/256/232.md +0 -20
- package/templates/cursor/.cursor/commands/sr-/350/251/263/347/264/260/350/250/255/350/250/210.md +0 -9
- package/templates/cursor/.cursorrules +0 -26
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# spec-runner 判定の単一入口。振る舞い仕様に沿って「フェーズ・ゲート・状態・グレード」を扱う。
|
|
3
|
+
# 使用: spec-runner-core.sh [--phase] [--json] | --gate [GRADE] | --status | --grade
|
|
4
|
+
# cmd-dispatch.sh(次のステップ・ゲート確認・ブランチ作成)から呼ばれる。
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo ".")}"
|
|
8
|
+
cd "$REPO_ROOT"
|
|
9
|
+
STEPS_DIR="${STEPS_DIR:-$REPO_ROOT/.spec-runner/steps}"
|
|
10
|
+
LOCK_FILE=".spec-runner/phase-locks.json"
|
|
11
|
+
PROJECT_JSON=".spec-runner/project.json"
|
|
12
|
+
|
|
13
|
+
MODE="phase"
|
|
14
|
+
JSON_MODE=false
|
|
15
|
+
GATE_GRADE=""
|
|
16
|
+
while [[ $# -gt 0 ]]; do
|
|
17
|
+
case "$1" in
|
|
18
|
+
--phase) MODE="phase" ;;
|
|
19
|
+
--json) JSON_MODE=true ;;
|
|
20
|
+
--gate) MODE="gate"; GATE_GRADE="${2:-}"; shift ;;
|
|
21
|
+
--status) MODE="status" ;;
|
|
22
|
+
--grade) MODE="grade" ;;
|
|
23
|
+
*) [[ "$MODE" == "gate" && -z "$GATE_GRADE" ]] && GATE_GRADE="$1" ;;
|
|
24
|
+
esac
|
|
25
|
+
shift
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
# === 共通: lock / grade / branch を一度だけ読む ===
|
|
29
|
+
has_charter_lock=0
|
|
30
|
+
has_domain_lock=0
|
|
31
|
+
has_arch_lock=0
|
|
32
|
+
has_infra_lock=0
|
|
33
|
+
if [[ -f "$LOCK_FILE" ]] && command -v jq >/dev/null 2>&1; then
|
|
34
|
+
[[ "$(jq -r '.charter.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] && has_charter_lock=1
|
|
35
|
+
[[ "$(jq -r '.domain.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] && has_domain_lock=1
|
|
36
|
+
[[ "$(jq -r '.architecture.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] && has_arch_lock=1
|
|
37
|
+
[[ "$(jq -r '.infra.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] && has_infra_lock=1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
grade="LOOP1"
|
|
41
|
+
if [[ -f ".spec-runner/grade-history.json" ]] && command -v jq >/dev/null 2>&1; then
|
|
42
|
+
grade=$(jq -r '.current_grade // "LOOP1"' .spec-runner/grade-history.json 2>/dev/null || echo "LOOP1")
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
branch=$(git branch --show-current 2>/dev/null || echo "")
|
|
46
|
+
branch_prefix="feature"
|
|
47
|
+
test_dir="tests"
|
|
48
|
+
test_pattern="*.spec.*"
|
|
49
|
+
if [[ -f "$PROJECT_JSON" ]] && command -v jq >/dev/null 2>&1; then
|
|
50
|
+
p=$(jq -r '.naming.branch_prefix // empty' "$PROJECT_JSON" 2>/dev/null)
|
|
51
|
+
[[ -n "$p" ]] && branch_prefix="$p"
|
|
52
|
+
d=$(jq -r '.test_design.dir // empty' "$PROJECT_JSON" 2>/dev/null)
|
|
53
|
+
[[ -n "$d" ]] && test_dir="$d"
|
|
54
|
+
pat=$(jq -r '.test_design.pattern // empty' "$PROJECT_JSON" 2>/dev/null)
|
|
55
|
+
[[ -n "$pat" ]] && test_pattern="$pat"
|
|
56
|
+
fi
|
|
57
|
+
on_uc_branch=0
|
|
58
|
+
on_other_work_branch=0
|
|
59
|
+
current_uc_id=""
|
|
60
|
+
other_work_pattern="work|infra|cicd"
|
|
61
|
+
if [[ -f "$PROJECT_JSON" ]] && command -v jq >/dev/null 2>&1; then
|
|
62
|
+
ow=$(jq -r '.naming.other_work_prefixes[]? // empty' "$PROJECT_JSON" 2>/dev/null | tr '\n' '|' | sed 's/|$//')
|
|
63
|
+
[[ -n "$ow" ]] && other_work_pattern="$ow"
|
|
64
|
+
fi
|
|
65
|
+
if [[ "$branch" =~ ^${branch_prefix}/UC-[0-9]{3}- ]]; then
|
|
66
|
+
on_uc_branch=1
|
|
67
|
+
current_uc_id="${branch#*/}"
|
|
68
|
+
elif [[ "$branch" =~ ^${branch_prefix}/(${other_work_pattern})/ ]]; then
|
|
69
|
+
on_other_work_branch=1
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# === ゲート確認モード ===
|
|
73
|
+
run_gate() {
|
|
74
|
+
exit_error() { echo "GATE: $1" >&2; exit 1; }
|
|
75
|
+
GRD="${GATE_GRADE:-$grade}"
|
|
76
|
+
[[ -f "$LOCK_FILE" ]] || exit_error "phase-locks.json が存在しません"
|
|
77
|
+
command -v jq >/dev/null 2>&1 || exit_error "jq がインストールされていません(例: brew install jq)"
|
|
78
|
+
|
|
79
|
+
check_required_paths() {
|
|
80
|
+
local key="$1"
|
|
81
|
+
local list
|
|
82
|
+
if [[ -f "$PROJECT_JSON" ]]; then
|
|
83
|
+
list=$(jq -r --arg k "$key" '.required_docs[$k][]? // empty' "$PROJECT_JSON" 2>/dev/null)
|
|
84
|
+
fi
|
|
85
|
+
if [[ -z "$list" ]]; then return 1; fi
|
|
86
|
+
while IFS= read -r path; do
|
|
87
|
+
[[ -z "$path" ]] && continue
|
|
88
|
+
if [[ -f "$path" ]]; then
|
|
89
|
+
:
|
|
90
|
+
elif [[ -d "$path" ]]; then
|
|
91
|
+
count=$(find "$path" -maxdepth 1 -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
92
|
+
[[ "${count:-0}" -ge 1 ]] || exit_error "必須: $path に 1 件以上の .md がありません"
|
|
93
|
+
else
|
|
94
|
+
exit_error "必須: $path が存在しません"
|
|
95
|
+
fi
|
|
96
|
+
done <<< "$list"
|
|
97
|
+
return 0
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if check_required_paths "charter"; then :; else
|
|
101
|
+
[[ -f "docs/01_憲章/憲章.md" ]] || exit_error "憲章.md が存在しません"
|
|
102
|
+
fi
|
|
103
|
+
if [[ "$GRD" == "LOOP1" ]]; then
|
|
104
|
+
[[ "$(jq -r '.charter.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] || exit_error "Phase 0 未完了(phase-locks.json の charter.completed)"
|
|
105
|
+
jq -e '.charter.reviewed_by' "$LOCK_FILE" >/dev/null 2>&1 || exit_error "憲章に署名がありません(charter.reviewed_by)"
|
|
106
|
+
echo "Phase 0: OK"
|
|
107
|
+
fi
|
|
108
|
+
if [[ "$GRD" != "LOOP1" ]]; then
|
|
109
|
+
[[ "$(jq -r '.domain.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] || exit_error "Phase 1 未完了"
|
|
110
|
+
if check_required_paths "domain"; then :; else
|
|
111
|
+
for doc in ユビキタス言語辞書 ドメインモデル 集約; do
|
|
112
|
+
[[ -f "docs/02_ドメイン設計/${doc}.md" ]] || exit_error "${doc}.md が存在しません"
|
|
113
|
+
done
|
|
114
|
+
fi
|
|
115
|
+
echo "Phase 1: OK"
|
|
116
|
+
[[ "$(jq -r '.architecture.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] || exit_error "Phase 2 未完了"
|
|
117
|
+
if check_required_paths "architecture"; then :; else
|
|
118
|
+
[[ -f "docs/03_アーキテクチャ/パターン選定.md" ]] || exit_error "パターン選定.md が存在しません"
|
|
119
|
+
[[ -f "docs/03_アーキテクチャ/インフラ方針.md" ]] || exit_error "インフラ方針.md が存在しません"
|
|
120
|
+
[[ $(find "docs/03_アーキテクチャ/設計判断記録/" -name "*.md" 2>/dev/null | wc -l) -gt 0 ]] || exit_error "ADR が 1 件もありません"
|
|
121
|
+
fi
|
|
122
|
+
echo "Phase 2: OK"
|
|
123
|
+
fi
|
|
124
|
+
if [[ "$GRD" == "A" ]]; then
|
|
125
|
+
[[ "$(jq -r '.infra.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] || exit_error "Grade A: インフラ設計未完了"
|
|
126
|
+
if check_required_paths "grade_a"; then :; else
|
|
127
|
+
[[ -f "docs/04_インフラ設計/schema.dbml" ]] || exit_error "Grade A 必須: docs/04_インフラ設計/schema.dbml が存在しません"
|
|
128
|
+
fi
|
|
129
|
+
echo "Phase 4 (Grade A): OK"
|
|
130
|
+
fi
|
|
131
|
+
if [[ "$GRD" == "A" || "$GRD" == "B" ]]; then
|
|
132
|
+
uc_count=$(find docs/05_ユースケース仕様 -mindepth 2 -maxdepth 2 -name "UC-*.md" 2>/dev/null | wc -l)
|
|
133
|
+
if [[ "${uc_count:-0}" -gt 0 ]]; then
|
|
134
|
+
uc_reviewed_count=$(jq -r '.uc_reviewed // [] | length' "$LOCK_FILE" 2>/dev/null || echo 0)
|
|
135
|
+
[[ "${uc_reviewed_count:-0}" -gt 0 ]] || exit_error "Gate 3: uc_reviewed に少なくとも1件の UC 識別子を登録してください"
|
|
136
|
+
if check_required_paths "gate3_openapi"; then :; else
|
|
137
|
+
[[ -f "docs/06_API仕様/openapi.yaml" ]] || exit_error "Gate 3: docs/06_API仕様/openapi.yaml が存在しません"
|
|
138
|
+
fi
|
|
139
|
+
echo "Gate 3 (UC+OpenAPI): OK"
|
|
140
|
+
fi
|
|
141
|
+
test_design_ok=0
|
|
142
|
+
[[ "$(jq -r '.test_design.completed // false' "$LOCK_FILE" 2>/dev/null)" == "true" ]] && test_design_ok=1
|
|
143
|
+
if [[ $test_design_ok -eq 1 ]] || [[ -d "$test_dir" && -n "$(find "$test_dir" -type f -name "$test_pattern" 2>/dev/null | head -1)" ]]; then
|
|
144
|
+
echo "Gate 5 (テスト設計): OK"
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
if [[ "$GRD" == "A" || "$GRD" == "B" || "$GRD" == "C" ]]; then
|
|
148
|
+
if [[ -f ".spec-runner/scripts/test/require-tests-green.sh" ]]; then
|
|
149
|
+
.spec-runner/scripts/test/require-tests-green.sh 2>/dev/null && echo "Gate 6 (テスト通過): OK" || true
|
|
150
|
+
elif [[ -f "docker-compose.yml" ]] || [[ -f "compose.yml" ]]; then
|
|
151
|
+
docker compose run --rm app npm test 2>/dev/null && echo "Gate 6 (テスト通過): OK" || true
|
|
152
|
+
elif [[ -f "package.json" ]]; then
|
|
153
|
+
npm test 2>/dev/null && echo "Gate 6 (テスト通過): OK" || true
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
echo "ゲート確認: 通過"
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# === フェーズ判定モード ===
|
|
160
|
+
run_phase() {
|
|
161
|
+
phase=0
|
|
162
|
+
phase_name_ja=""
|
|
163
|
+
command=""
|
|
164
|
+
command_file=""
|
|
165
|
+
|
|
166
|
+
if [[ $has_charter_lock -eq 0 ]]; then
|
|
167
|
+
phase=0; phase_name_ja="憲章策定"; command="憲章"; command_file="$STEPS_DIR/憲章.md"
|
|
168
|
+
elif [[ $has_domain_lock -eq 0 ]]; then
|
|
169
|
+
phase=1; phase_name_ja="ドメイン設計"; command="ドメイン設計"; command_file="$STEPS_DIR/ドメイン設計.md"
|
|
170
|
+
elif [[ $has_arch_lock -eq 0 ]]; then
|
|
171
|
+
phase=2; phase_name_ja="アーキテクチャ選択"; command="実装計画"; command_file="$STEPS_DIR/実装計画.md"
|
|
172
|
+
elif [[ $on_uc_branch -eq 1 ]]; then
|
|
173
|
+
uc_spec=""
|
|
174
|
+
if [[ -n "$current_uc_id" ]]; then
|
|
175
|
+
for f in docs/05_ユースケース仕様/*/"${current_uc_id}.md"; do [[ -f "$f" ]] && uc_spec="$f" && break; done
|
|
176
|
+
fi
|
|
177
|
+
if [[ -z "$uc_spec" ]]; then
|
|
178
|
+
phase=3; phase_name_ja="UC 仕様書"; command="仕様策定"; command_file="$STEPS_DIR/仕様策定.md"
|
|
179
|
+
else
|
|
180
|
+
uc_dir=$(basename "$uc_spec" .md)
|
|
181
|
+
reviewed=0
|
|
182
|
+
[[ -f "$LOCK_FILE" ]] && command -v jq >/dev/null 2>&1 && jq -e --arg u "$uc_dir" '.uc_reviewed[]? == $u' "$LOCK_FILE" 2>/dev/null | grep -q true && reviewed=1
|
|
183
|
+
if [[ $reviewed -eq 0 ]]; then
|
|
184
|
+
phase=3; phase_name_ja="UC 仕様書(レビュー通過まで)"; command="曖昧さ解消"; command_file="$STEPS_DIR/曖昧さ解消.md"
|
|
185
|
+
else
|
|
186
|
+
if [[ "$grade" == "A" ]] && [[ $has_infra_lock -eq 0 ]]; then
|
|
187
|
+
phase=4; phase_name_ja="インフラ詳細設計"; command="実装計画"; command_file="$STEPS_DIR/実装計画.md"
|
|
188
|
+
else
|
|
189
|
+
has_tests=0
|
|
190
|
+
[[ -d "$test_dir" ]] && [[ -n "$(find "$test_dir" -type f -name "$test_pattern" 2>/dev/null | head -1)" ]] && has_tests=1
|
|
191
|
+
if [[ $has_tests -eq 0 ]]; then
|
|
192
|
+
phase=5; phase_name_ja="テスト設計"; command="テスト設計"; command_file="$STEPS_DIR/テスト設計.md"
|
|
193
|
+
else
|
|
194
|
+
phase=6; phase_name_ja="実装"; command="実装"; command_file="$STEPS_DIR/実装.md"
|
|
195
|
+
fi
|
|
196
|
+
fi
|
|
197
|
+
fi
|
|
198
|
+
fi
|
|
199
|
+
else
|
|
200
|
+
if [[ $on_other_work_branch -eq 1 ]]; then
|
|
201
|
+
phase=3; phase_name_ja="その他作業(CI/CD・インフラ等)"; command="その他作業"; command_file="$STEPS_DIR/その他作業.md"
|
|
202
|
+
elif [[ $has_arch_lock -eq 0 ]]; then
|
|
203
|
+
phase=2; phase_name_ja="アーキテクチャ選択"; command="実装計画"; command_file="$STEPS_DIR/実装計画.md"
|
|
204
|
+
else
|
|
205
|
+
phase=3; phase_name_ja="UC 開始(仕様策定)"; command="仕様策定"; command_file="$STEPS_DIR/仕様策定.md"
|
|
206
|
+
fi
|
|
207
|
+
fi
|
|
208
|
+
|
|
209
|
+
if [[ "$JSON_MODE" == true ]]; then
|
|
210
|
+
if command -v jq >/dev/null 2>&1; then
|
|
211
|
+
jq -cn --argjson phase $phase --arg name "$phase_name_ja" --arg cmd "$command" --arg file "$command_file" --arg grade "$grade" \
|
|
212
|
+
'{phase:$phase, phase_name_ja:$name, command:$cmd, command_file:$file, grade:$grade}'
|
|
213
|
+
else
|
|
214
|
+
echo "{\"phase\":$phase,\"phase_name_ja\":\"$phase_name_ja\",\"command\":\"$command\",\"command_file\":\"$command_file\",\"grade\":\"$grade\"}"
|
|
215
|
+
fi
|
|
216
|
+
else
|
|
217
|
+
echo "現在フェーズ: Phase $phase($phase_name_ja)"
|
|
218
|
+
echo "推奨コマンド: $command"
|
|
219
|
+
echo "コマンドファイル: $command_file"
|
|
220
|
+
echo "グレード: $grade"
|
|
221
|
+
if [[ $on_uc_branch -eq 0 ]] && [[ -n "$branch" ]]; then
|
|
222
|
+
echo ""
|
|
223
|
+
echo "注意: main 等のままの修正は危険です。UC 用ブランチを作成してから作業してください(仕様策定ステップでブランチ作成)。"
|
|
224
|
+
fi
|
|
225
|
+
fi
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
# === 状態表示(lock 一覧)===
|
|
229
|
+
run_status() {
|
|
230
|
+
echo "=== spec-runner フェーズ状況 ==="
|
|
231
|
+
echo "グレード: $grade"
|
|
232
|
+
echo ""
|
|
233
|
+
echo "Lock(.spec-runner/phase-locks.json):"
|
|
234
|
+
if [[ -f "$LOCK_FILE" ]] && command -v jq >/dev/null 2>&1; then
|
|
235
|
+
for sec in charter domain architecture infra test_design; do
|
|
236
|
+
val=$(jq -r --arg s "$sec" '.[$s].completed // false' "$LOCK_FILE" 2>/dev/null)
|
|
237
|
+
[[ "$val" == "true" ]] && echo " ✓ $sec" || echo " - $sec"
|
|
238
|
+
done
|
|
239
|
+
else
|
|
240
|
+
echo " phase-locks.json が存在しないか jq がインストールされていません"
|
|
241
|
+
fi
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
# === グレード判定チェックリスト ===
|
|
245
|
+
run_grade() {
|
|
246
|
+
echo "=== spec-runner グレード判定 ==="
|
|
247
|
+
echo ""
|
|
248
|
+
echo "STEP 1: 作業の種別を判定する"
|
|
249
|
+
echo " → 既存UCの修正・バグfix: Grade C 確定(以降の判定不要)"
|
|
250
|
+
echo " → 新規UC: STEP 2 へ"
|
|
251
|
+
echo ""
|
|
252
|
+
echo "STEP 2: Grade B 仮置きで UC 草稿を作成する"
|
|
253
|
+
echo " → AI と対話して UC 仕様書の草稿(status: draft)を作成する"
|
|
254
|
+
echo " → この時点ではまだブランチ作成・コミット不要"
|
|
255
|
+
echo ""
|
|
256
|
+
echo "STEP 3: UC 草稿を見て Grade を確定する"
|
|
257
|
+
echo " 以下のいずれかが草稿に含まれていれば Grade A:"
|
|
258
|
+
echo " □ 新しいDB・テーブル・コレクションの追加が必要"
|
|
259
|
+
echo " □ 外部API・SaaS との新規連携が必要"
|
|
260
|
+
echo " □ 新規クラウドサービスの追加が必要(S3バケット・Redisクラスタ等)"
|
|
261
|
+
echo " □ ネットワーク構成の変更が必要"
|
|
262
|
+
echo " □ CI/CDパイプラインの変更が必要"
|
|
263
|
+
echo " → 一つでも該当: Grade A 確定 → ブランチ作成 → Phase 3(UC仕様書)へ"
|
|
264
|
+
echo " → 全て非該当: Grade B 確定 → ブランチ作成 → Phase 3(UC仕様書)へ(草稿を流用)"
|
|
265
|
+
echo ""
|
|
266
|
+
echo "判定結果は .spec-runner/grade-history.json に記録する(ブランチ名には含めない)。"
|
|
267
|
+
echo "迷ったら上位グレードを選ぶ。"
|
|
268
|
+
echo ""
|
|
269
|
+
echo "現在の記録: current_grade = $grade"
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
# === 実行 ===
|
|
273
|
+
if [[ "$MODE" == "gate" ]]; then
|
|
274
|
+
echo "=== ゲート確認(グレード: ${GATE_GRADE:-$grade}) ==="
|
|
275
|
+
run_gate
|
|
276
|
+
elif [[ "$MODE" == "status" ]]; then
|
|
277
|
+
run_status
|
|
278
|
+
elif [[ "$MODE" == "grade" ]]; then
|
|
279
|
+
run_grade
|
|
280
|
+
else
|
|
281
|
+
run_phase
|
|
282
|
+
fi
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# テストコマンドを実行し、すべてグリーンでないと終了コード 1 を返す。
|
|
3
|
+
# 実装ステップの「完了検証」で必須。コマンドは .spec-runner/project.json の test_command.run で指定。
|
|
4
|
+
# 未設定時はプロジェクトを検出して候補を実行し、設定を促す。
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo ".")}"
|
|
8
|
+
cd "$REPO_ROOT"
|
|
9
|
+
SPEC_RUNNER="${REPO_ROOT}/.spec-runner"
|
|
10
|
+
PROJECT_JSON="${SPEC_RUNNER}/project.json"
|
|
11
|
+
LEGACY_TEST_JSON="${SPEC_RUNNER}/test-command.json"
|
|
12
|
+
|
|
13
|
+
# 設定を読む: project.json の test_command.run → 後方互換で test-command.json の run
|
|
14
|
+
get_run_command() {
|
|
15
|
+
local run=""
|
|
16
|
+
if [[ -f "$PROJECT_JSON" ]]; then
|
|
17
|
+
if command -v jq >/dev/null 2>&1; then
|
|
18
|
+
run=$(jq -r '.test_command.run // empty' "$PROJECT_JSON" 2>/dev/null)
|
|
19
|
+
else
|
|
20
|
+
run=$(grep -o '"run"[[:space:]]*:[[:space:]]*"[^"]*"' "$PROJECT_JSON" 2>/dev/null | head -1 | sed 's/.*"\([^"]*\)" *$/\1/')
|
|
21
|
+
fi
|
|
22
|
+
fi
|
|
23
|
+
if [[ -z "$run" ]] && [[ -f "$LEGACY_TEST_JSON" ]]; then
|
|
24
|
+
if command -v jq >/dev/null 2>&1; then
|
|
25
|
+
run=$(jq -r '.run // empty' "$LEGACY_TEST_JSON" 2>/dev/null)
|
|
26
|
+
else
|
|
27
|
+
run=$(grep -o '"run"[[:space:]]*:[[:space:]]*"[^"]*"' "$LEGACY_TEST_JSON" 2>/dev/null | sed 's/.*"\([^"]*\)" *$/\1/')
|
|
28
|
+
fi
|
|
29
|
+
fi
|
|
30
|
+
echo -n "$run"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# 未設定時に検出して実行するコマンドを決める
|
|
34
|
+
detect_and_run() {
|
|
35
|
+
if [[ -f "package.json" ]] && grep -q '"test"' package.json 2>/dev/null; then
|
|
36
|
+
echo "npm test"
|
|
37
|
+
return
|
|
38
|
+
fi
|
|
39
|
+
if [[ -f "pyproject.toml" ]]; then
|
|
40
|
+
if command -v poetry >/dev/null 2>&1; then
|
|
41
|
+
echo "poetry run pytest"
|
|
42
|
+
else
|
|
43
|
+
echo "pytest"
|
|
44
|
+
fi
|
|
45
|
+
return
|
|
46
|
+
fi
|
|
47
|
+
if [[ -f "go.mod" ]]; then
|
|
48
|
+
echo "go test ./..."
|
|
49
|
+
return
|
|
50
|
+
fi
|
|
51
|
+
if [[ -f "docker-compose.yml" ]] || [[ -f "docker-compose.yaml" ]]; then
|
|
52
|
+
# サービス名は app を仮定(未設定時は検出のみで実行しない)
|
|
53
|
+
echo ""
|
|
54
|
+
return
|
|
55
|
+
fi
|
|
56
|
+
echo ""
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
RUN_CMD=$(get_run_command)
|
|
60
|
+
|
|
61
|
+
# 未設定なら検出
|
|
62
|
+
if [[ -z "$RUN_CMD" ]]; then
|
|
63
|
+
RUN_CMD=$(detect_and_run)
|
|
64
|
+
if [[ -z "$RUN_CMD" ]]; then
|
|
65
|
+
echo "require-tests-green: テストコマンドが未設定です。.spec-runner/project.json の test_command.run を設定するか、初期化(init-project.sh)を実行してください。" >&2
|
|
66
|
+
echo " 例: project.json に \"test_command\": {\"run\": \"npm test\"} を追加" >&2
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
echo "require-tests-green: project.json に test_command がありません。検出したコマンドで実行します: $RUN_CMD" >&2
|
|
70
|
+
echo " 恒久設定: 初期化で設定するか、project.json に test_command.run を追加してください。" >&2
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
echo "require-tests-green: テストを実行しています($RUN_CMD)..."
|
|
74
|
+
if eval "$RUN_CMD"; then
|
|
75
|
+
echo "require-tests-green: すべてグリーンです。実装完了の条件(テスト)を満たしています。"
|
|
76
|
+
exit 0
|
|
77
|
+
else
|
|
78
|
+
echo "" >&2
|
|
79
|
+
echo "require-tests-green: テストが失敗しました。実装完了とみなせません。" >&2
|
|
80
|
+
echo " テストを修正し、再度 .spec-runner/scripts/test/require-tests-green.sh を実行してください。" >&2
|
|
81
|
+
echo " コマンドを変更する場合は .spec-runner/project.json の test_command.run を編集するか、初期化(init-project.sh)を実行してください。" >&2
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# spec-runner エントリポイント。次のステップ(現在フェーズ・やるべきステップ .md)を返す。
|
|
3
|
+
# 使用: .spec-runner/spec-runner.sh [次のステップ] [--json|--lock|--グレード]
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
|
7
|
+
cd "$REPO_ROOT"
|
|
8
|
+
SR="$REPO_ROOT/.spec-runner/scripts"
|
|
9
|
+
|
|
10
|
+
cmd="${1:-}"
|
|
11
|
+
shift || true
|
|
12
|
+
|
|
13
|
+
case "$cmd" in
|
|
14
|
+
次のステップ|"")
|
|
15
|
+
if [[ "$cmd" == "" ]]; then
|
|
16
|
+
# 引数なしは「次のステップ」として扱う(/spec-runner スラッシュコマンド用)
|
|
17
|
+
:
|
|
18
|
+
fi
|
|
19
|
+
case "${1:-}" in
|
|
20
|
+
--lock) exec "$SR/spec-runner-core.sh" --status ;;
|
|
21
|
+
--グレード) exec "$SR/spec-runner-core.sh" --grade ;;
|
|
22
|
+
*) exec "$SR/spec-runner-core.sh" --phase "$@" ;;
|
|
23
|
+
esac
|
|
24
|
+
;;
|
|
25
|
+
*)
|
|
26
|
+
echo "spec-runner: 引数なし、または「次のステップ」[--json|--lock|--グレード] のみ対応しています。" >&2
|
|
27
|
+
echo " 使用例: .spec-runner/spec-runner.sh 次のステップ --json" >&2
|
|
28
|
+
exit 1
|
|
29
|
+
;;
|
|
30
|
+
esac
|
package/templates/.spec-runner/steps//343/201/235/343/201/256/344/273/226/344/275/234/346/245/255.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# その他作業(CI/CD・インフラ・共通設定など)
|
|
2
|
+
|
|
3
|
+
**このブランチは UC 用ではありません。** `feature/<接頭辞>/xxx` 形式(接頭辞は project.json の **naming.other_work_prefixes** で指定)のため、spec-runner は「CI/CD 構築」「インフラ」「共通設定」など UC 以外の作業用とみなします。
|
|
4
|
+
|
|
5
|
+
## ブランチの例
|
|
6
|
+
|
|
7
|
+
- `feature/cicd/github-actions` … CI/CD 構築
|
|
8
|
+
- `feature/infra/docker` … インフラ・コンテナ
|
|
9
|
+
- `feature/work/setup-tooling` … 共通ツール導入
|
|
10
|
+
|
|
11
|
+
接頭辞は **project.json の naming.other_work_prefixes** に配列で書く(既定: work, infra, cicd)。プロジェクトに合わせて追加・変更してよい。
|
|
12
|
+
|
|
13
|
+
## やること
|
|
14
|
+
|
|
15
|
+
- **spec-runner の UC ステップ(仕様策定〜実装)は対象外**。このステップを出したまま、通常の開発フローで進めてよい。
|
|
16
|
+
- 必要に応じて **実装計画.md**(`.spec-runner/steps/実装計画.md`)を参照し、設計書(docs/03, docs/04, docs/06 等)に沿って作業する。
|
|
17
|
+
- 作業が終わったら main にマージするか、UC 用ブランチ(`feature/UC-NNN-xxx`)に切り替えて spec-runner を再実行する。
|
|
18
|
+
|
|
19
|
+
## 注意
|
|
20
|
+
|
|
21
|
+
- phase-locks の `uc_reviewed` や UC 用の判定には影響しない。このブランチ用の lock は不要。
|
|
22
|
+
- 再度 spec-runner で「次のステップ」を見たい場合は、UC 用ブランチにチェックアウトするか、main に戻る。
|
package/templates/.spec-runner/steps//343/202/277/343/202/271/343/202/257/344/270/200/350/246/247.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
> **実装タスクの整理**: UC 仕様書(UC-NNN-xxx.md)の**一番下**に「## タスク」または「## タスク一覧」セクションを追加・更新する。タスクは UC の .md 内に記載する。テスト設計は別ステップ「テスト設計」で行う。
|
|
2
|
+
|
|
3
|
+
## ユーザー入力
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
$ARGUMENTS
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
(空でない場合)処理を進める前にユーザー入力を**必ず**考慮すること。
|
|
10
|
+
|
|
11
|
+
## 実行前チェック
|
|
12
|
+
|
|
13
|
+
**拡張フックの確認(タスク生成前)**:
|
|
14
|
+
- プロジェクトルートに `.spec-runner/extensions.yml` が存在するか確認する(任意。なければスキップ)
|
|
15
|
+
- あれば `hooks.before_tasks` のエントリを読む
|
|
16
|
+
- YAML がパースできない・不正な場合はフック確認を静かにスキップして続行
|
|
17
|
+
- `enabled: true` のフックだけを対象にする
|
|
18
|
+
- 各フックの `condition` 式の解釈・評価は行わない(条件が空でなければフックをスキップし、評価は HookExecutor に任せる)
|
|
19
|
+
- 実行可能なフックごとに `optional` に応じて出力する:
|
|
20
|
+
- **任意フック**(`optional: true`): 拡張名・コマンド・説明・プロンプト・実行方法を表示
|
|
21
|
+
- **必須フック**(`optional: false`): 拡張名・実行するコマンドを表示し、結果を待ってから概要に進む
|
|
22
|
+
- 登録フックがなければ、または `.spec-runner/extensions.yml` がなければ静かにスキップする
|
|
23
|
+
|
|
24
|
+
## 概要
|
|
25
|
+
|
|
26
|
+
1. **セットアップ**: リポジトリルートから `.spec-runner/scripts/lib/uc-context.sh --json` を実行する。現在ブランチは feature/UC-NNN-xxx。JSON から FEATURE_SPEC(UC 仕様書)、FEATURE_DIR をパースする。パスは絶対パス。引数にシングルクォートを含む場合はエスケープ(例: 'I'\''m Groot')またはダブルクォートを使う。
|
|
27
|
+
|
|
28
|
+
2. **設計ドキュメントの読み込み**: FEATURE_SPEC(UC 仕様書)を必須で読む。UC の「## 実装方針」から技術スタック・構造を読む。無ければ UC 仕様書とプロジェクト既存ファイルから推測する。
|
|
29
|
+
|
|
30
|
+
3. **タスク整理ワークフローの実行**:
|
|
31
|
+
- UC の「## 実装方針」から技術スタック・プロジェクト構造を抽出する。無ければ UC 仕様書とプロジェクト既存ファイルから推測する。
|
|
32
|
+
- spec.md を読み、優先度(P1, P2, P3 等)付きユーザーストーリーを抽出する
|
|
33
|
+
- data-model.md があればエンティティを抽出しユーザーストーリーにマッピングする
|
|
34
|
+
- contracts/ があればインターフェース契約をユーザーストーリーにマッピングする
|
|
35
|
+
- research.md があれば決定をセットアップタスクに反映する
|
|
36
|
+
- ユーザーストーリーごとにタスクを整理して生成する(下記タスク生成ルール参照)
|
|
37
|
+
- ユーザーストーリー完了順の依存グラフを作成する
|
|
38
|
+
- ストーリーごとに並列実行例を作成する
|
|
39
|
+
- タスクの完全性を検証する(各ユーザーストーリーに必要なタスクが揃い、独立してテスト可能であること)
|
|
40
|
+
|
|
41
|
+
4. **UC 仕様書へのタスクセクション追加・更新**: **FEATURE_SPEC(UC の .md)の一番下**に「## タスク」または「## タスク一覧」見出しを置き、以下で埋める。既にセクションがあれば内容を更新する。
|
|
42
|
+
- UC の実装方針から正しい機能名
|
|
43
|
+
- Phase 1: セットアップタスク(プロジェクト初期化)
|
|
44
|
+
- Phase 2: 基盤タスク(全ユーザーストーリーの前提)
|
|
45
|
+
- Phase 3 以降: 優先度順でユーザーストーリーごとに 1 フェーズ
|
|
46
|
+
- 各フェーズにストーリー目標・独立したテスト基準・(依頼があれば)テスト・実装タスクを含める
|
|
47
|
+
- 最終フェーズ: 仕上げと横断的関心事
|
|
48
|
+
- 全タスクは下記チェックリスト形式に厳守する
|
|
49
|
+
- 各タスクに明確なファイルパスを付ける
|
|
50
|
+
- ストーリー完了順の依存セクション
|
|
51
|
+
- ストーリーごとの並列実行例
|
|
52
|
+
- 実装戦略セクション(MVP 優先・段階的リリース)
|
|
53
|
+
|
|
54
|
+
5. **報告**: 更新した UC 仕様書(FEATURE_SPEC)のパスとタスクセクションの概要を出力する:
|
|
55
|
+
- タスク総数
|
|
56
|
+
- ユーザーストーリーごとのタスク数
|
|
57
|
+
- 並列実行の機会
|
|
58
|
+
- ストーリーごとの独立したテスト基準
|
|
59
|
+
- 推奨 MVP スコープ(多くはユーザーストーリー 1 のみ)
|
|
60
|
+
- 形式検証: 全タスクがチェックリスト形式(チェックボックス・ID・ラベル・ファイルパス)に従っていることを確認する
|
|
61
|
+
|
|
62
|
+
6. **拡張フックの確認(タスク追記後)**: UC へのタスクセクション追記後に `.spec-runner/extensions.yml` の `hooks.after_tasks` があれば同様のルールで表示または実行する(なければスキップ)。
|
|
63
|
+
|
|
64
|
+
タスク整理の文脈: $ARGUMENTS
|
|
65
|
+
|
|
66
|
+
UC 内のタスクセクションは即実行可能であること。各タスクは LLM が追加文脈なしで完了できる程度に具体的であること。**確定事項の完了は健全性確認(check.sh)で検証される。**
|
|
67
|
+
|
|
68
|
+
## タスク生成ルール
|
|
69
|
+
|
|
70
|
+
**重要**: 独立した実装・テストを可能にするため、タスクは**ユーザーストーリーごと**に整理すること。
|
|
71
|
+
|
|
72
|
+
**テストは任意**: 機能仕様またはユーザーが TDD を依頼した場合にのみ、テストタスクを生成する。
|
|
73
|
+
|
|
74
|
+
### チェックリスト形式(必須)
|
|
75
|
+
|
|
76
|
+
各タスクは次の形式に厳守する:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
- [ ] [TaskID] [P?] [Story?] 説明(ファイルパス付き)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**構成要素**:
|
|
83
|
+
|
|
84
|
+
1. **チェックボックス**: 常に `- [ ]` で始める
|
|
85
|
+
2. **タスク ID**: 実行順の連番(T001, T002, T003 ...)
|
|
86
|
+
3. **[P] マーカー**: 並列実行可能なタスクのみ付ける(別ファイル・未完了タスクに依存しない)
|
|
87
|
+
4. **[Story] ラベル**: ユーザーストーリーフェーズのタスクのみ必須。形式: [US1], [US2], [US3] 等(spec.md のユーザーストーリーに対応)。セットアップ・基盤・仕上げフェーズにはストーリーラベルを付けない
|
|
88
|
+
5. **説明**: 明確なアクションと正確なファイルパス
|
|
89
|
+
|
|
90
|
+
**例**:
|
|
91
|
+
|
|
92
|
+
- ✅ 正: `- [ ] T001 実装計画に従いプロジェクト構造を作成する`
|
|
93
|
+
- ✅ 正: `- [ ] T005 [P] src/middleware/auth.py に認証ミドルウェアを実装する`
|
|
94
|
+
- ✅ 正: `- [ ] T012 [P] [US1] src/models/user.py に User モデルを作成する`
|
|
95
|
+
- ✅ 正: `- [ ] T014 [US1] src/services/user_service.py に UserService を実装する`
|
|
96
|
+
- ❌ 誤: `- [ ] User モデルを作成する`(ID とストーリーラベルがない)
|
|
97
|
+
- ❌ 誤: `T001 [US1] モデルを作成する`(チェックボックスがない)
|
|
98
|
+
- ❌ 誤: `- [ ] [US1] User モデルを作成する`(タスク ID がない)
|
|
99
|
+
- ❌ 誤: `- [ ] T001 [US1] モデルを作成する`(ファイルパスがない)
|
|
100
|
+
|
|
101
|
+
### タスクの整理
|
|
102
|
+
|
|
103
|
+
1. **ユーザーストーリー(spec.md)を主軸とする**:
|
|
104
|
+
- 各ユーザーストーリー(P1, P2, P3 ...)に 1 フェーズ
|
|
105
|
+
- ストーリーに関連するコンポーネントをすべてマッピング: モデル・サービス・インターフェース/UI・(依頼があれば)テスト
|
|
106
|
+
- ストーリー間の依存を記載する(多くのストーリーは独立)
|
|
107
|
+
|
|
108
|
+
2. **契約から**:
|
|
109
|
+
- 各インターフェース契約を、それを提供するユーザーストーリーに対応づける
|
|
110
|
+
- テストを依頼されている場合: 各契約に対して、そのストーリーフェーズの実装前に契約テストタスク [P] を置く
|
|
111
|
+
|
|
112
|
+
3. **データモデルから**:
|
|
113
|
+
- 各エンティティを、それを必要とするユーザーストーリーに対応づける
|
|
114
|
+
- 複数ストーリーで使うエンティティは、最初のストーリーまたはセットアップフェーズに含める
|
|
115
|
+
- リレーションは適切なストーリーフェーズのサービス層タスクで扱う
|
|
116
|
+
|
|
117
|
+
4. **セットアップ/インフラから**:
|
|
118
|
+
- 共通インフラ → Phase 1(セットアップ)
|
|
119
|
+
- 基盤/ブロッキングタスク → Phase 2(基盤)
|
|
120
|
+
- ストーリー固有のセットアップ → そのストーリーのフェーズ内
|
|
121
|
+
|
|
122
|
+
### フェーズ構成
|
|
123
|
+
|
|
124
|
+
- **Phase 1**: セットアップ(プロジェクト初期化)
|
|
125
|
+
- **Phase 2**: 基盤(全ユーザーストーリーの前提。ユーザーストーリーより前に完了必須)
|
|
126
|
+
- **Phase 3 以降**: 優先度順のユーザーストーリー(P1, P2, P3 ...)
|
|
127
|
+
- 各ストーリー内: (依頼があれば)テスト → モデル → サービス → エンドポイント → 統合
|
|
128
|
+
- 各フェーズは独立してテスト可能な増分として完了させる
|
|
129
|
+
- **最終フェーズ**: 仕上げと横断的関心事
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
完了したら次のステップに進む。
|