spec-runner 1.0.6 → 1.0.8

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.
Files changed (93) hide show
  1. package/README.md +36 -184
  2. package/bin/spec-runner.js +157 -703
  3. package/install.sh +6 -12
  4. package/package.json +3 -7
  5. package/templates/.spec-runner/hooks/pre-commit +47 -0
  6. package/templates/.spec-runner/hooks/pre-push +9 -0
  7. package/templates/.spec-runner/project.json.example +27 -0
  8. package/templates/.spec-runner/scripts/branch/uc-next-start.sh +172 -0
  9. package/templates/.spec-runner/scripts/check.sh +403 -0
  10. package/templates/.spec-runner/scripts/spec-runner-core.sh +411 -0
  11. package/templates/.spec-runner/scripts/test/require-tests-green.sh +27 -0
  12. package/templates/.spec-runner/spec-runner.sh +30 -0
  13. package/templates/.spec-runner/steps/steps.json +171 -0
  14. package/templates/.spec-runner/steps//343/201/235/343/201/256/344/273/226/344/275/234/346/245/255.md +34 -0
  15. package/templates/.spec-runner/steps//343/202/277/343/202/271/343/202/257/344/270/200/350/246/247.md +95 -0
  16. 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 +80 -0
  17. package/templates/.spec-runner/steps//343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +57 -0
  18. package/templates/.spec-runner/steps//343/203/211/343/203/241/343/202/244/343/203/263/350/250/255/350/250/210.md +52 -0
  19. package/templates/.spec-runner/steps//344/273/225/346/247/230/347/255/226/345/256/232.md +173 -0
  20. package/templates/.spec-runner/steps//345/210/206/346/236/220.md +104 -0
  21. package/templates/.spec-runner/steps//345/256/237/350/243/205.md +79 -0
  22. package/templates/.spec-runner/steps//345/256/237/350/243/205/350/250/210/347/224/273.md +96 -0
  23. package/templates/.spec-runner/steps//346/206/262/347/253/240.md +95 -0
  24. package/templates/.spec-runner/steps//346/233/226/346/230/247/343/201/225/350/247/243/346/266/210.md +99 -0
  25. package/templates/.spec-runner/templates/UC-N-MMDD-/345/210/244/346/226/255/350/250/230/351/214/262/343/203/206/343/203/263/343/203/227/343/203/254.md +33 -0
  26. package/templates/.spec-runner/templates/UC-N-/343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271/345/220/215.md +20 -0
  27. package/templates/.spec-runner/templates/grade-history.json +5 -0
  28. package/templates/.spec-runner/templates/phase-locks.json +29 -0
  29. package/templates/.spec-runner/templates//343/203/211/343/203/241/343/202/244/343/203/263/343/203/242/343/203/207/343/203/253.md +21 -0
  30. package/templates/.spec-runner/templates//343/203/246/343/203/223/343/202/255/343/202/277/343/202/271/350/250/200/350/252/236/350/276/236/346/233/270.md +16 -0
  31. package/templates/.spec-runner/templates//346/206/262/347/253/240.md +51 -0
  32. package/templates/.spec-runner/templates//351/233/206/347/264/204.md +46 -0
  33. package/templates/spec-runner-command.md +42 -0
  34. package/templates/base/.github/PULL_REQUEST_TEMPLATE.md +0 -43
  35. package/templates/base/.github/workflows/phase-gate-check.yml +0 -216
  36. package/templates/base/scripts/spec-runner.sh +0 -1144
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. package/templates/base/templates/README.md +0 -32
  44. 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
  45. 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
  46. 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
  47. 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
  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//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
  49. 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
  50. package/templates/claude/.claude/commands/sr-/343/202/262/343/203/274/343/203/210/350/250/255/345/256/232.md +0 -9
  51. package/templates/claude/.claude/commands/sr-/343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +0 -9
  52. package/templates/claude/.claude/commands/sr-/343/203/254/343/203/223/343/203/245/343/203/274.md +0 -9
  53. package/templates/claude/.claude/commands/sr-/344/273/225/346/247/230.md +0 -9
  54. package/templates/claude/.claude/commands/sr-/344/277/256/346/255/243.md +0 -9
  55. package/templates/claude/.claude/commands/sr-/345/210/235/346/234/237/345/214/226.md +0 -10
  56. package/templates/claude/.claude/commands/sr-/345/256/237/350/243/205.md +0 -9
  57. package/templates/claude/.claude/commands/sr-/346/206/262/347/253/240.md +0 -9
  58. package/templates/claude/.claude/commands/sr-/346/246/202/350/246/201/350/250/255/350/250/210.md +0 -9
  59. package/templates/claude/.claude/commands/sr-/347/212/266/346/205/213.md +0 -9
  60. package/templates/claude/.claude/commands/sr-/347/267/212/346/200/245/344/277/256/346/255/243.md +0 -9
  61. package/templates/claude/.claude/commands/sr-/350/250/255/345/256/232.md +0 -11
  62. package/templates/claude/.claude/commands/sr-/350/251/263/347/264/260/350/250/255/350/250/210.md +0 -9
  63. package/templates/claude/.claude/hooks/pre-tool-use.sh +0 -79
  64. package/templates/claude/.claude/settings.json +0 -29
  65. package/templates/claude/CLAUDE.md +0 -141
  66. package/templates/copilot/.github/copilot-instructions.md +0 -25
  67. 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
  68. 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
  69. package/templates/copilot/.github/prompts/sr-/343/203/254/343/203/223/343/203/245/343/203/274.prompt.md +0 -14
  70. package/templates/copilot/.github/prompts/sr-/344/273/225/346/247/230.prompt.md +0 -13
  71. package/templates/copilot/.github/prompts/sr-/344/277/256/346/255/243.prompt.md +0 -14
  72. package/templates/copilot/.github/prompts/sr-/345/210/235/346/234/237/345/214/226.prompt.md +0 -15
  73. package/templates/copilot/.github/prompts/sr-/345/256/237/350/243/205.prompt.md +0 -13
  74. package/templates/copilot/.github/prompts/sr-/346/206/262/347/253/240.prompt.md +0 -13
  75. package/templates/copilot/.github/prompts/sr-/346/246/202/350/246/201/350/250/255/350/250/210.prompt.md +0 -13
  76. package/templates/copilot/.github/prompts/sr-/347/212/266/346/205/213.prompt.md +0 -13
  77. package/templates/copilot/.github/prompts/sr-/347/267/212/346/200/245/344/277/256/346/255/243.prompt.md +0 -14
  78. package/templates/copilot/.github/prompts/sr-/350/250/255/345/256/232.prompt.md +0 -13
  79. package/templates/copilot/.github/prompts/sr-/350/251/263/347/264/260/350/250/255/350/250/210.prompt.md +0 -14
  80. package/templates/cursor/.cursor/commands/sr-/343/202/262/343/203/274/343/203/210/350/250/255/345/256/232.md +0 -11
  81. package/templates/cursor/.cursor/commands/sr-/343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +0 -9
  82. package/templates/cursor/.cursor/commands/sr-/343/203/254/343/203/223/343/203/245/343/203/274.md +0 -9
  83. package/templates/cursor/.cursor/commands/sr-/344/273/225/346/247/230.md +0 -9
  84. package/templates/cursor/.cursor/commands/sr-/344/277/256/346/255/243.md +0 -9
  85. package/templates/cursor/.cursor/commands/sr-/345/210/235/346/234/237/345/214/226.md +0 -35
  86. package/templates/cursor/.cursor/commands/sr-/345/256/237/350/243/205.md +0 -9
  87. package/templates/cursor/.cursor/commands/sr-/346/206/262/347/253/240.md +0 -9
  88. package/templates/cursor/.cursor/commands/sr-/346/246/202/350/246/201/350/250/255/350/250/210.md +0 -9
  89. package/templates/cursor/.cursor/commands/sr-/347/212/266/346/205/213.md +0 -9
  90. package/templates/cursor/.cursor/commands/sr-/347/267/212/346/200/245/344/277/256/346/255/243.md +0 -9
  91. package/templates/cursor/.cursor/commands/sr-/350/250/255/345/256/232.md +0 -20
  92. package/templates/cursor/.cursor/commands/sr-/350/251/263/347/264/260/350/250/255/350/250/210.md +0 -9
  93. package/templates/cursor/.cursorrules +0 -26
package/install.sh CHANGED
@@ -1,13 +1,11 @@
1
1
  #!/usr/bin/env bash
2
- # =============================================================================
3
- # spec-runner インストーラー (curl 方式)
2
+ # spec-runner 用インストーラ(curl 用)
4
3
  #
5
4
  # 使い方:
6
- # curl -sSL https://raw.githubusercontent.com/spec-runner/spec-runner/main/install.sh | bash
5
+ # curl -sSL https://raw.githubusercontent.com/TEEE88/spec-runner/main/install.sh | bash
7
6
  #
8
7
  # または wget:
9
- # wget -qO- https://raw.githubusercontent.com/spec-runner/spec-runner/main/install.sh | bash
10
- # =============================================================================
8
+ # wget -qO- https://raw.githubusercontent.com/TEEE88/spec-runner/main/install.sh | bash
11
9
 
12
10
  set -e
13
11
 
@@ -25,12 +23,11 @@ die() { echo -e "${RED}ERROR:${NC} $*" >&2; exit 1; }
25
23
 
26
24
  echo ""
27
25
  echo -e "${BOLD}╔════════════════════════════════════════╗${NC}"
28
- echo -e "${BOLD}║ spec-runner インストーラー ║${NC}"
29
- echo -e "${BOLD}║ AI-driven DDD Phase Gate System ║${NC}"
26
+ echo -e "${BOLD}║ spec-runner インストーラ ║${NC}"
27
+ echo -e "${BOLD}║ フェーズ駆動 / 次のステップ方式 ║${NC}"
30
28
  echo -e "${BOLD}╚════════════════════════════════════════╝${NC}"
31
29
  echo ""
32
30
 
33
- # ── Node.js チェック ──────────────────────────────────────────────────────────
34
31
  if command -v node &>/dev/null; then
35
32
  NODE_VERSION=$(node --version | sed 's/v//')
36
33
  NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d. -f1)
@@ -42,7 +39,6 @@ else
42
39
  die "Node.js がインストールされていません。\n https://nodejs.org からインストールしてください"
43
40
  fi
44
41
 
45
- # ── jq チェック ───────────────────────────────────────────────────────────────
46
42
  if command -v jq &>/dev/null; then
47
43
  ok "jq $(jq --version)"
48
44
  else
@@ -56,10 +52,9 @@ else
56
52
  else
57
53
  die "jq を手動でインストールしてください: https://stedolan.github.io/jq/download/"
58
54
  fi
59
- ok "jq インストール完了"
55
+ ok "jq インストール済み"
60
56
  fi
61
57
 
62
- # ── git チェック ──────────────────────────────────────────────────────────────
63
58
  if command -v git &>/dev/null; then
64
59
  ok "git $(git --version | awk '{print $3}')"
65
60
  else
@@ -70,7 +65,6 @@ echo ""
70
65
  info "npx spec-runner を実行します..."
71
66
  echo ""
72
67
 
73
- # ── npm/npx で実行 ────────────────────────────────────────────────────────────
74
68
  if command -v npx &>/dev/null; then
75
69
  npx spec-runner@latest
76
70
  elif command -v npm &>/dev/null; then
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "spec-runner",
3
- "version": "1.0.6",
4
- "description": "AI-driven DDD phase gate system — design-first enforcement for Claude Code, Cursor, and Copilot",
3
+ "version": "1.0.8",
4
+ "description": "フェーズ駆動で設計先行を強制。npx .spec-runner を展開し、次のステップ .md に従って進める",
5
5
  "license": "MIT",
6
6
  "bin": {
7
7
  "spec-runner": "bin/spec-runner.js"
@@ -22,6 +22,7 @@
22
22
  "nextjs",
23
23
  "spec-kit"
24
24
  ],
25
+ "scripts": {},
25
26
  "files": [
26
27
  "bin/",
27
28
  "templates/",
@@ -29,11 +30,6 @@
29
30
  "README.md",
30
31
  "LICENSE"
31
32
  ],
32
- "dependencies": {
33
- "chalk": "^4.1.2",
34
- "enquirer": "^2.3.6",
35
- "ora": "^5.4.1"
36
- },
37
33
  "repository": {
38
34
  "type": "git",
39
35
  "url": "git+https://github.com/TEEE88/spec-runner.git"
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ # spec-runner pre-commit: ブランチ名チェック + 命名規則チェック(Section 8-4)
3
+
4
+ set -e
5
+ REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"
6
+ [[ -n "$REPO_ROOT" ]] || exit 0
7
+
8
+ branch=$(git branch --show-current)
9
+
10
+ pj="$REPO_ROOT/.spec-runner/project.json"
11
+ [[ -f "$pj" ]] || { echo "pre-commit: project.json がありません: $pj" >&2; exit 1; }
12
+ command -v jq >/dev/null 2>&1 || { echo "pre-commit: jq が必要です(brew install jq)" >&2; exit 1; }
13
+ bp="$(jq -r '.naming.branch_prefix // "feature"' "$pj" 2>/dev/null)"
14
+ uc_id_pat="$(jq -r '.naming.uc_id_pattern // "UC-[0-9]+"' "$pj" 2>/dev/null)"
15
+ other_work="$(jq -r '.naming.other_work_prefixes[]? | . + "/.+"' "$pj" 2>/dev/null | tr '\n' '|' | sed 's/|$//')"
16
+ [[ -z "$other_work" ]] && other_work="work/.+|infra/.+|cicd/.+"
17
+ valid_pattern="^(main|develop|${bp}/(${uc_id_pat}-.+|${other_work})|fix/${uc_id_pat}-.+|release/[0-9]+\\.[0-9]+\\.[0-9]+.*|hotfix/[0-9]+\\.[0-9]+\\.[0-9]+-.+)$"
18
+
19
+ if ! echo "$branch" | grep -qE "$valid_pattern"; then
20
+ echo "❌ ブランチ名が規則違反: $branch"
21
+ echo " 正しい形式:"
22
+ if [[ -f "$REPO_ROOT/.spec-runner/project.json" ]] && command -v jq >/dev/null 2>&1; then
23
+ bp=$(jq -r '.naming.branch_prefix // "feature"' "$REPO_ROOT/.spec-runner/project.json" 2>/dev/null || echo "feature")
24
+ else
25
+ bp="feature"
26
+ fi
27
+ echo " ${bp}/{UC-ID}-{kebab-description} (新規UC、UC-IDは project.json の uc_id_pattern)"
28
+ echo " ${bp}/cicd/xxx ${bp}/infra/xxx (その他作業、project.json の other_work_prefixes)"
29
+ echo " fix/{UC-ID}-{kebab-description} (修正)"
30
+ echo " release/{semver} (リリース)"
31
+ echo " hotfix/{semver}-{kebab-description} (緊急修正)"
32
+ exit 1
33
+ fi
34
+
35
+ # 命名規則チェック(.spec-runner スクリプトがある場合のみ実行)
36
+ if [[ -d "$REPO_ROOT/src" ]]; then
37
+ while IFS= read -r dir; do
38
+ [[ -z "$dir" ]] && continue
39
+ base=$(basename "$dir")
40
+ if ! echo "$base" | grep -qE '^[a-z][a-z0-9-]*$'; then
41
+ echo "NAMING: フォルダ名「$dir」はkebab-caseで命名してください" >&2
42
+ exit 1
43
+ fi
44
+ done < <(find "$REPO_ROOT/src/" -type d 2>/dev/null || true)
45
+ fi
46
+
47
+ exit 0
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+ # spec-runner pre-push: main/develop への直接 push 禁止(Section 8-5)
3
+
4
+ branch=$(git branch --show-current)
5
+ if [[ "$branch" == "main" || "$branch" == "develop" ]]; then
6
+ echo "❌ main / develop への直接 push は禁止です。PR を作成してください"
7
+ exit 1
8
+ fi
9
+ exit 0
@@ -0,0 +1,27 @@
1
+ {
2
+ "_comment": "AI が編集して作成。other_work_prefixes は UC 以外の作業用ブランチ(例: feature/cicd/xxx)。",
3
+ "_comment_required_docs": "required_docs は steps.json を単一ソースにするため、\"steps:<common.docsキー>[/suffix]\" を指定できる(例: steps:openapi, steps:domain_root/集約.md)。",
4
+ "naming": {
5
+ "branch_prefix": "feature",
6
+ "uc_id_pattern": "UC-[0-9]+",
7
+ "uc_spec_basename": "{uc_id}-{slug}.md",
8
+ "adr_basename": "MMDD-{title}.md",
9
+ "docs_05_categories": true,
10
+ "other_work_prefixes": ["work", "infra", "cicd"]
11
+ },
12
+ "required_docs": {
13
+ "charter": ["steps:charter"],
14
+ "domain": ["steps:domain_root/ユビキタス言語辞書.md", "steps:domain_root/ドメインモデル.md", "steps:domain_root/集約.md"],
15
+ "architecture": ["steps:architecture_root/パターン選定.md", "steps:architecture_root/インフラ方針.md", "steps:architecture_root/設計判断記録"],
16
+ "grade_a": ["steps:infra_root/schema.dbml"],
17
+ "gate3_openapi": ["steps:openapi"]
18
+ },
19
+ "test_design": {
20
+ "dir": "tests",
21
+ "pattern": "*.spec.*",
22
+ "require_uc_prefixed_tests": true
23
+ },
24
+ "test_command": {
25
+ "run": "npm test"
26
+ }
27
+ }
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env bash
2
+ # 次の UC を開始する: main に切り替え、feature/UC-N-xxx ブランチを作成する。
3
+ # 使用例:
4
+ # ./uc-next-start.sh # 次 UC 番号を自動検出。説明はプロンプトまたは "next-uc" で作成
5
+ # ./uc-next-start.sh task-update # 次 UC 番号 + 説明 "task-update" でブランチ作成
6
+ # ./uc-next-start.sh task-update 認証 # 次 UC 番号 + 説明 + カテゴリ
7
+ # ./uc-next-start.sh UC-2 task-update # 指定 UC + 説明
8
+ # ./uc-next-start.sh UC-2 task-update 認証 # 指定 UC + 説明 + カテゴリ
9
+ # ./uc-next-start.sh --yes task-update # 確認なしで実行
10
+ # 実行後は次のステップに進む旨を案内する。
11
+
12
+ set -e
13
+ REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo ".")}"
14
+ cd "$REPO_ROOT"
15
+ BRANCH_DIR="$(cd "$(dirname "$0")" && pwd)"
16
+
17
+ YES_MODE=false
18
+ ARGS=()
19
+ for a in "$@"; do
20
+ case "$a" in
21
+ --yes|-y) YES_MODE=true ;;
22
+ *) ARGS+=("$a") ;;
23
+ esac
24
+ done
25
+
26
+ PROJECT_JSON="$REPO_ROOT/.spec-runner/project.json"
27
+ [[ -f "$PROJECT_JSON" ]] || { echo "uc-next-start: project.json がありません: $PROJECT_JSON" >&2; exit 1; }
28
+ command -v jq >/dev/null 2>&1 || { echo "uc-next-start: jq が必要です(brew install jq)" >&2; exit 1; }
29
+ UC_ID_RE="$(jq -r '.naming.uc_id_pattern' "$PROJECT_JSON")"
30
+ BRANCH_PREFIX="$(jq -r '.naming.branch_prefix' "$PROJECT_JSON")"
31
+ [[ -n "$UC_ID_RE" && "$UC_ID_RE" != "null" && -n "$BRANCH_PREFIX" && "$BRANCH_PREFIX" != "null" ]] || {
32
+ echo "uc-next-start: project.json の naming.uc_id_pattern / branch_prefix が未設定です" >&2
33
+ exit 1
34
+ }
35
+
36
+ next_uc_id() {
37
+ # docs/02_ユースケース仕様/<カテゴリ>/UC-*.md から次に使う UC-N を返す
38
+ local dir="$REPO_ROOT/docs/02_ユースケース仕様"
39
+ mkdir -p "$dir"
40
+ local max=0
41
+ for f in "$dir"/*/UC-*.md; do
42
+ [[ -e "$f" ]] || continue
43
+ base=$(basename "$f" .md)
44
+ if [[ "$base" =~ ^(${UC_ID_RE})- ]]; then
45
+ uc_id="${BASH_REMATCH[1]}"
46
+ digits=$(echo "$uc_id" | tr -cd '0-9')
47
+ [[ -z "$digits" ]] && continue
48
+ n=$((10#$digits))
49
+ [[ $n -gt $max ]] && max=$n
50
+ fi
51
+ done
52
+ printf "UC-%d\n" $((max + 1))
53
+ }
54
+
55
+ NEXT_UC="$(next_uc_id)"
56
+ DESC=""
57
+ CATEGORY=""
58
+
59
+ # ファイル題名は日本語優先にするため、スクリプト引数の「生の説明」を保持する
60
+ RAW_DESC=""
61
+ if [[ ${#ARGS[@]} -ge 2 ]] && [[ "${ARGS[0]}" =~ ^${UC_ID_RE}$ ]]; then
62
+ NEXT_UC="${ARGS[0]}"
63
+ DESC="${ARGS[1]}"
64
+ RAW_DESC="${ARGS[1]}"
65
+ CATEGORY="${ARGS[2]:-}"
66
+ elif [[ ${#ARGS[@]} -ge 1 ]]; then
67
+ DESC="${ARGS[0]}"
68
+ RAW_DESC="${ARGS[0]}"
69
+ CATEGORY="${ARGS[1]:-}"
70
+ fi
71
+
72
+ # 説明が無ければデフォルト(next-uc や UC 番号ベース)
73
+ if [[ -z "$DESC" ]]; then
74
+ if [[ "$YES_MODE" == true ]]; then
75
+ DESC="next-uc"
76
+ else
77
+ echo "次の UC 用ブランチを作成します。"
78
+ echo " UC: $NEXT_UC"
79
+ echo -n " 説明(英数字・ハイフン推奨。日本語のみの場合は uc-001 等にフォールバック。Enter で \"next-uc\"): "
80
+ read -r DESC
81
+ DESC="${DESC:-next-uc}"
82
+ fi
83
+ fi
84
+
85
+ # 説明は英小文字・ハイフン(Git ブランチ名は ASCII のみ)。日本語など非 ASCII はサニタイズで除去される
86
+ # macOS(BSD sed) でも動くように、連続ハイフンは 's/--*/-/g' で圧縮する
87
+ DESC=$(echo "$DESC" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-*//' | sed 's/-*$//')
88
+ # サニタイズ後に空(日本語のみの説明など)の場合は UC 番号ベースのスラグでフォールバック
89
+ [[ -z "$DESC" ]] && DESC="uc-$(echo "$NEXT_UC" | sed 's/^UC-//')"
90
+ BRANCH_NAME="${BRANCH_PREFIX}/${NEXT_UC}-${DESC}"
91
+
92
+ # UC 仕様書ファイル名は必ず日本語にする(題名が ASCII のみなら「要確認」にする)
93
+ DOC_TITLE="$RAW_DESC"
94
+ if [[ -z "$DOC_TITLE" ]]; then
95
+ DOC_TITLE="要確認"
96
+ else
97
+ # 非ASCIIが無い(= 英数字/記号のみ)なら、日本語題名が無い扱いにして要確認へ
98
+ if echo "$DOC_TITLE" | LC_ALL=C grep -q '^[ -~]*$'; then
99
+ DOC_TITLE="要確認"
100
+ fi
101
+ fi
102
+ # ファイル名に危険な文字が入らないように除去(日本語は許可)
103
+ DOC_TITLE=$(echo "$DOC_TITLE" | sed 's/[\\\\\\/\\:\\*\\?\\\"\\<\\>\\|]/ /g' | sed 's/[[:space:]]\\+/ /g' | sed 's/^ *//; s/ *$//')
104
+ [[ -z "$DOC_TITLE" ]] && DOC_TITLE="要確認"
105
+
106
+ # カテゴリ(省略時はデフォルト)。日本語カテゴリは許可し、危険文字だけ除去。
107
+ CATEGORY="${CATEGORY:-ユースケース}"
108
+ CATEGORY=$(echo "$CATEGORY" | sed 's/[^a-zA-Z0-9_ーぁ-んァ-ン一-龥\-]//g')
109
+ [[ -z "$CATEGORY" ]] && CATEGORY="ユースケース"
110
+
111
+ if git rev-parse --verify "$BRANCH_NAME" >/dev/null 2>&1; then
112
+ echo "Error: ブランチ '$BRANCH_NAME' は既に存在します。" >&2
113
+ exit 1
114
+ fi
115
+
116
+ CURRENT=$(git branch --show-current 2>/dev/null || echo "")
117
+ MAIN_BRANCH="main"
118
+ if ! git rev-parse --verify "$MAIN_BRANCH" >/dev/null 2>&1; then
119
+ MAIN_BRANCH="master"
120
+ if ! git rev-parse --verify "$MAIN_BRANCH" >/dev/null 2>&1; then
121
+ echo "Error: main も master も存在しません。" >&2
122
+ exit 1
123
+ fi
124
+ fi
125
+
126
+ if [[ "$YES_MODE" != true ]]; then
127
+ echo "次の UC を開始する準備をします。"
128
+ echo " $MAIN_BRANCH にチェックアウトし、ブランチ \"$BRANCH_NAME\" を作成します。"
129
+ echo -n " 実行してよろしいですか? [y/N]: "
130
+ read -r ans
131
+ case "$ans" in
132
+ [yY]|[yY][eE][sS]) ;;
133
+ *) echo "キャンセルしました。"; exit 0 ;;
134
+ esac
135
+ fi
136
+
137
+ git checkout "$MAIN_BRANCH"
138
+ git pull --ff-only 2>/dev/null || true
139
+
140
+ # ブランチ作成 + UC 仕様書作成(統合)
141
+ UC_ID_PATTERN="^${UC_ID_RE}$"
142
+ if ! echo "$NEXT_UC" | grep -qE "$UC_ID_PATTERN"; then
143
+ echo "Error: UC-ID が命名規則に合いません: $NEXT_UC(期待: $UC_ID_PATTERN)" >&2
144
+ exit 1
145
+ fi
146
+ valid_uc_pattern="^${BRANCH_PREFIX}/${UC_ID_RE}-[a-z0-9-]+\$"
147
+ if ! echo "$BRANCH_NAME" | grep -qE "$valid_uc_pattern"; then
148
+ echo "Error: ブランチ名が命名規則に合いません: $BRANCH_NAME(期待: ${BRANCH_PREFIX}/<UC-ID>-kebab-description)" >&2
149
+ exit 1
150
+ fi
151
+
152
+ git checkout -b "$BRANCH_NAME"
153
+ echo "Created branch: $BRANCH_NAME"
154
+
155
+ FEATURE_DIR="docs/02_ユースケース仕様/${CATEGORY}"
156
+ UC_DOC="${FEATURE_DIR}/${NEXT_UC}-${DOC_TITLE}.md"
157
+ mkdir -p "$FEATURE_DIR"
158
+ # UC ごとの判断ログ置き場(任意だが、作成しておくと運用が安定する)
159
+ mkdir -p "${FEATURE_DIR}/判断記録"
160
+ # テンプレ: 修正・改善は .spec-runner/templates/UC-N-ユースケース名.md を編集。プレースホルダ UC-N → UC番号, {ユースケース名} → 題名
161
+ TEMPLATE="$REPO_ROOT/.spec-runner/templates/UC-N-ユースケース名.md"
162
+ if [[ -f "$TEMPLATE" ]]; then
163
+ sed "s/UC-N/${NEXT_UC}/g; s/{ユースケース名}/${DOC_TITLE}/g" "$TEMPLATE" > "$UC_DOC"
164
+ echo "Created: $UC_DOC"
165
+ else
166
+ touch "$UC_DOC"
167
+ echo "# ${NEXT_UC}: ${DOC_TITLE}" >> "$UC_DOC"
168
+ echo "Created: $UC_DOC"
169
+ fi
170
+
171
+ echo ""
172
+ echo "次の UC 用ブランチの準備ができました。次のステップに進んでください。"