spec-runner 1.0.7 → 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 (39) hide show
  1. package/README.md +16 -9
  2. package/bin/spec-runner.js +112 -144
  3. package/package.json +1 -6
  4. package/templates/.spec-runner/hooks/pre-commit +25 -11
  5. package/templates/.spec-runner/project.json.example +10 -8
  6. package/templates/.spec-runner/scripts/branch/uc-next-start.sh +100 -9
  7. package/templates/.spec-runner/scripts/check.sh +396 -13
  8. package/templates/.spec-runner/scripts/spec-runner-core.sh +286 -157
  9. package/templates/.spec-runner/scripts/test/require-tests-green.sh +7 -63
  10. package/templates/.spec-runner/steps/steps.json +171 -0
  11. package/templates/.spec-runner/steps//343/201/235/343/201/256/344/273/226/344/275/234/346/245/255.md +25 -13
  12. package/templates/.spec-runner/steps//343/202/277/343/202/271/343/202/257/344/270/200/350/246/247.md +67 -104
  13. 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 +52 -78
  14. package/templates/.spec-runner/steps//343/203/206/343/202/271/343/203/210/350/250/255/350/250/210.md +41 -34
  15. package/templates/.spec-runner/steps//343/203/211/343/203/241/343/202/244/343/203/263/350/250/255/350/250/210.md +34 -14
  16. package/templates/.spec-runner/steps//344/273/225/346/247/230/347/255/226/345/256/232.md +161 -207
  17. package/templates/.spec-runner/steps//345/210/206/346/236/220.md +64 -127
  18. package/templates/.spec-runner/steps//345/256/237/350/243/205.md +67 -79
  19. package/templates/.spec-runner/steps//345/256/237/350/243/205/350/250/210/347/224/273.md +56 -56
  20. package/templates/.spec-runner/steps//346/206/262/347/253/240.md +67 -46
  21. package/templates/.spec-runner/steps//346/233/226/346/230/247/343/201/225/350/247/243/346/266/210.md +88 -148
  22. 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
  23. package/templates/.spec-runner/templates/{UC-NNN- → UC-N-}/343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271/345/220/215.md +1 -3
  24. package/templates/.spec-runner/templates/grade-history.json +5 -0
  25. package/templates/.spec-runner/templates/phase-locks.json +29 -0
  26. 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
  27. 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
  28. package/templates/.spec-runner/templates//346/206/262/347/253/240.md +51 -0
  29. package/templates/.spec-runner/templates//351/233/206/347/264/204.md +46 -0
  30. package/templates/.spec-runner/scripts/branch/create-uc-branch.sh +0 -105
  31. package/templates/.spec-runner/scripts/branch/uc-next-id.sh +0 -17
  32. package/templates/.spec-runner/scripts/check/drift.sh +0 -66
  33. package/templates/.spec-runner/scripts/check/health.sh +0 -103
  34. package/templates/.spec-runner/scripts/check/naming.sh +0 -51
  35. package/templates/.spec-runner/scripts/check/schema-drift.sh +0 -74
  36. package/templates/.spec-runner/scripts/check/schema-sync.sh +0 -153
  37. package/templates/.spec-runner/scripts/lib/uc-context.sh +0 -75
  38. package/templates/.spec-runner/scripts/openapi/openapi-generate.sh +0 -207
  39. package/templates/.spec-runner/scripts/setup/init-project.sh +0 -152
@@ -1,207 +0,0 @@
1
- #!/usr/bin/env bash
2
- # OpenAPI から型・クライアントを生成する。
3
- # ターゲットは「今のドキュメント」(.spec-runner/openapi-generator-targets.json) にだけ載せる。
4
- # 対話で generator と output を聞き、生成後に「名前を付けて保存」するとドキュメントに追記され、次から名前で呼べる。
5
- # 使用例:
6
- # ./openapi-generate.sh # 対話: 既存から選択 or 新規(generator/output を聞いて保存)
7
- # ./openapi-generate.sh typescript # ドキュメントに登録した名前で生成
8
- # ./openapi-generate.sh --generator python --output src/api_python # 直接指定(終了時に「保存する?」と聞く)
9
- # ./openapi-generate.sh --list
10
-
11
- set -e
12
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
- REPO_ROOT="${REPO_ROOT:-$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null)}"
14
- [[ -n "$REPO_ROOT" ]] || REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
15
- cd "$REPO_ROOT"
16
-
17
- INPUT_SPEC="${REPO_ROOT}/docs/06_API仕様/openapi.yaml"
18
- CONFIG="${REPO_ROOT}/.spec-runner/openapi-generator-targets.json"
19
-
20
- if [[ ! -f "$INPUT_SPEC" ]]; then
21
- echo "openapi-generate: openapi.yaml がありません(docs/06_API仕様/openapi.yaml)。" >&2
22
- exit 1
23
- fi
24
-
25
- if ! command -v jq >/dev/null 2>&1; then
26
- echo "openapi-generate: 対話でドキュメントを更新するために jq が必要です(brew install jq)。" >&2
27
- exit 1
28
- fi
29
-
30
- # 設定ファイルを用意(無ければ空の targets)
31
- ensure_config() {
32
- if [[ ! -f "$CONFIG" ]]; then
33
- mkdir -p "$(dirname "$CONFIG")"
34
- echo '{"targets":{},"inputSpec":"docs/06_API仕様/openapi.yaml"}' > "$CONFIG"
35
- fi
36
- }
37
-
38
- # JSON から generator と output を取得
39
- get_from_config() {
40
- local target="$1"
41
- if [[ -f "$CONFIG" ]]; then
42
- local g o
43
- g=$(jq -r --arg t "$target" '.targets[$t].generator // empty' "$CONFIG" 2>/dev/null)
44
- o=$(jq -r --arg t "$target" '.targets[$t].output // empty' "$CONFIG" 2>/dev/null)
45
- if [[ -n "$g" ]] && [[ -n "$o" ]]; then
46
- echo "${g}|${o}"
47
- fi
48
- fi
49
- }
50
-
51
- # ドキュメントにターゲットを 1 件追加
52
- save_target() {
53
- local name="$1"
54
- local generator="$2"
55
- local output="$3"
56
- local desc="${4:-}"
57
- ensure_config
58
- if [[ -z "$name" ]]; then return; fi
59
- # 既存 targets にマージ。description は任意。
60
- jq --arg n "$name" --arg g "$generator" --arg o "$output" --arg d "$desc" \
61
- '.targets[$n] = (if $d != "" then {"generator":$g,"output":$o,"description":$d} else {"generator":$g,"output":$o} end)' \
62
- "$CONFIG" > "${CONFIG}.tmp" && mv "${CONFIG}.tmp" "$CONFIG"
63
- echo " → .spec-runner/openapi-generator-targets.json に「$name」を追加しました。"
64
- }
65
-
66
- # 生成実行(共通)
67
- run_generate() {
68
- local generator="$1"
69
- local output="$2"
70
- echo "OpenAPI から生成: generator=$generator, output=$output"
71
- npx --yes @openapitools/openapi-generator-cli@latest generate \
72
- -i "$INPUT_SPEC" \
73
- -g "$generator" \
74
- -o "$REPO_ROOT/$output" \
75
- --additional-properties=supportsES6=true
76
- echo "生成完了: $output"
77
- }
78
-
79
- list_targets() {
80
- ensure_config
81
- echo "登録済みターゲット(.spec-runner/openapi-generator-targets.json):"
82
- if ! jq -e '.targets | length > 0' "$CONFIG" >/dev/null 2>&1; then
83
- echo " (なし)対話で追加してください: ./openapi-generate.sh"
84
- else
85
- jq -r '.targets | to_entries[] | " \(.key): generator=\(.value.generator), output=\(.value.output)"' "$CONFIG" 2>/dev/null || true
86
- fi
87
- echo ""
88
- echo "直接指定: --generator <name> --output <dir> 例: --generator ruby --output lib/api_ruby"
89
- echo "一覧: https://openapi-generator.tech/docs/generators/"
90
- exit 0
91
- }
92
-
93
- # 対話: 新規ターゲット(generator / output を聞き、生成してから名前を付けて保存)
94
- interactive_new() {
95
- local g o name desc
96
- echo "新規ターゲットを追加します。"
97
- read -r -p "Generator 名 (例: typescript-fetch, python, go): " g
98
- g=$(echo "$g" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
99
- if [[ -z "$g" ]]; then
100
- echo "Generator 名が空のため中止しました。" >&2
101
- exit 1
102
- fi
103
- read -r -p "出力ディレクトリ (例: src/api-client-ts): " o
104
- o=$(echo "$o" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
105
- if [[ -z "$o" ]]; then
106
- echo "出力ディレクトリが空のため中止しました。" >&2
107
- exit 1
108
- fi
109
- run_generate "$g" "$o"
110
- echo ""
111
- read -r -p "この組み合わせをドキュメントに保存しますか?名前 (空白でスキップ): " name
112
- name=$(echo "$name" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
113
- if [[ -n "$name" ]]; then
114
- read -r -p "説明 (任意): " desc
115
- save_target "$name" "$g" "$o" "$desc"
116
- fi
117
- }
118
-
119
- # 引数解析
120
- GENERATOR=""
121
- OUTPUT=""
122
- TARGET="${OPENAPI_TARGET:-}"
123
- while [[ $# -gt 0 ]]; do
124
- case "$1" in
125
- --list|-l) list_targets ;;
126
- -h|--help)
127
- echo "使用法: openapi-generate.sh [ターゲット名] | [--generator <name> --output <dir>]"
128
- echo " 引数なし → 対話: 登録済みから選択 or 新規追加(generator/output を聞いてドキュメントに保存)"
129
- echo " ターゲット名 → ドキュメントに登録した名前で生成"
130
- echo " --generator X --output Y → 直接生成。終了時に「ドキュメントに保存する?」と聞く"
131
- echo ""
132
- list_targets
133
- ;;
134
- --generator) GENERATOR="$2"; shift 2 ;;
135
- --output) OUTPUT="$2"; shift 2 ;;
136
- --*)
137
- echo "openapi-generate: 不明なオプション $1" >&2
138
- exit 1
139
- ;;
140
- *) TARGET="$1"; shift ;;
141
- esac
142
- done
143
-
144
- # 直接指定で生成 → 終了時に「保存する?」と聞く
145
- if [[ -n "$GENERATOR" ]] && [[ -n "$OUTPUT" ]]; then
146
- run_generate "$GENERATOR" "$OUTPUT"
147
- if [[ -t 0 ]]; then
148
- echo ""
149
- read -r -p "この組み合わせをドキュメントに保存しますか?名前 (空白でスキップ): " name
150
- name=$(echo "$name" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
151
- if [[ -n "$name" ]]; then
152
- read -r -p "説明 (任意): " desc
153
- save_target "$name" "$GENERATOR" "$OUTPUT" "$desc"
154
- fi
155
- fi
156
- exit 0
157
- fi
158
-
159
- # ターゲット名指定 → ドキュメントから取得して生成
160
- if [[ -n "$TARGET" ]]; then
161
- pair=$(get_from_config "$TARGET")
162
- if [[ -z "$pair" ]]; then
163
- echo "openapi-generate: 登録されていないターゲット「$TARGET」" >&2
164
- echo " --list で一覧。または引数なしで対話し、この名前で保存してください。" >&2
165
- exit 1
166
- fi
167
- IFS='|' read -r GENERATOR OUTPUT <<< "$pair"
168
- run_generate "$GENERATOR" "$OUTPUT"
169
- exit 0
170
- fi
171
-
172
- # 引数なし → 対話
173
- ensure_config
174
- keys=($(jq -r '.targets | keys[]' "$CONFIG" 2>/dev/null || true))
175
-
176
- if [[ ${#keys[@]} -eq 0 ]]; then
177
- # まだ 1 件もない → 新規追加フローへ
178
- interactive_new
179
- exit 0
180
- fi
181
-
182
- echo "ターゲットを選ぶか、新規追加します:"
183
- for i in "${!keys[@]}"; do
184
- echo " $((i+1))) ${keys[$i]}"
185
- done
186
- echo " n) 新規追加(generator / output を入力してドキュメントに保存)"
187
- read -r -p "番号または名前 [1]: " ans
188
- ans="${ans:-1}"
189
-
190
- if [[ "$ans" == "n" ]] || [[ "$ans" == "N" ]] || [[ "$ans" == "新規" ]]; then
191
- interactive_new
192
- exit 0
193
- fi
194
-
195
- if [[ "$ans" =~ ^[0-9]+$ ]] && [[ "$ans" -ge 1 ]] && [[ "$ans" -le ${#keys[@]} ]]; then
196
- TARGET="${keys[$((ans-1))]}"
197
- else
198
- TARGET="$ans"
199
- fi
200
-
201
- pair=$(get_from_config "$TARGET")
202
- if [[ -z "$pair" ]]; then
203
- echo "openapi-generate: 登録されていないターゲット「$TARGET」" >&2
204
- exit 1
205
- fi
206
- IFS='|' read -r GENERATOR OUTPUT <<< "$pair"
207
- run_generate "$GENERATOR" "$OUTPUT"
@@ -1,152 +0,0 @@
1
- #!/usr/bin/env bash
2
- # プロジェクト初期設定を AI と対話しながら行う。設定は .spec-runner/project.json に集約する。
3
- # 使用例: .spec-runner/scripts/setup/init-project.sh
4
-
5
- set -e
6
- REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo ".")}"
7
- cd "$REPO_ROOT"
8
- SPEC_RUNNER="$REPO_ROOT/.spec-runner"
9
- CONFIG="$SPEC_RUNNER/project.json"
10
-
11
- command -v jq >/dev/null 2>&1 || { echo "init-project: jq が必要です(brew install jq)" >&2; exit 1; }
12
-
13
- echo "=== spec-runner プロジェクト初期設定 ==="
14
- echo ""
15
-
16
- # --- 1. テストコマンド ---
17
- detect_test_command() {
18
- if [[ -f "package.json" ]] && grep -q '"test"' package.json 2>/dev/null; then
19
- echo "npm test"
20
- return
21
- fi
22
- if [[ -f "pyproject.toml" ]]; then
23
- command -v poetry >/dev/null 2>&1 && echo "poetry run pytest" || echo "pytest"
24
- return
25
- fi
26
- if [[ -f "go.mod" ]]; then
27
- echo "go test ./..."
28
- return
29
- fi
30
- echo ""
31
- }
32
-
33
- CURRENT_TEST=""
34
- [[ -f "$CONFIG" ]] && CURRENT_TEST=$(jq -r '.test_command.run // empty' "$CONFIG" 2>/dev/null)
35
- [[ -z "$CURRENT_TEST" ]] && [[ -f "$SPEC_RUNNER/test-command.json" ]] && CURRENT_TEST=$(jq -r '.run // empty' "$SPEC_RUNNER/test-command.json" 2>/dev/null)
36
- DETECTED=$(detect_test_command)
37
-
38
- echo "【1】テストコマンド(require-tests-green.sh が実行するコマンド)"
39
- if [[ -n "$CURRENT_TEST" ]]; then
40
- echo " 現在: $CURRENT_TEST"
41
- fi
42
- if [[ -n "$DETECTED" ]]; then
43
- echo " 検出候補: $DETECTED"
44
- fi
45
- echo " (1) 検出したコマンドを使う (2) 自分で入力 (Enter = 変更しない)"
46
- read -r choice
47
- case "$choice" in
48
- 1)
49
- if [[ -n "$DETECTED" ]]; then
50
- RUN_CMD="$DETECTED"
51
- else
52
- echo " 検出できませんでした。コマンドを入力してください(例: npm test):"
53
- read -r RUN_CMD
54
- fi
55
- ;;
56
- 2)
57
- echo " コマンドを入力(例: docker compose run --rm app npm test):"
58
- read -r RUN_CMD
59
- ;;
60
- *)
61
- RUN_CMD="${CURRENT_TEST:-$DETECTED}"
62
- ;;
63
- esac
64
- echo ""
65
-
66
- # --- 2. 命名規則 ---
67
- echo "【2】命名規則(ブランチ・UC 仕様書・設計判断記録のファイル名)"
68
- DEFAULT_BRANCH="feature"
69
- DEFAULT_UC="UC-NNN-xxx.md"
70
- DEFAULT_ADR="MMDD-題名.md"
71
- if [[ -f "$CONFIG" ]]; then
72
- DEFAULT_BRANCH=$(jq -r '.naming.branch_prefix // "feature"' "$CONFIG" 2>/dev/null)
73
- fi
74
- echo " ブランチ例: ${DEFAULT_BRANCH}/UC-001-create-task"
75
- echo " UC 仕様書例: docs/05_ユースケース仕様/<カテゴリ>/UC-001-create-task.md"
76
- echo " 設計判断記録例: docs/03_アーキテクチャ/設計判断記録/0314-アーキテクチャ選定.md"
77
- echo " 変更しますか? (y/N)"
78
- read -r change_naming
79
- if [[ "$change_naming" == "y" || "$change_naming" == "Y" ]]; then
80
- echo " ブランチ接頭辞(Enter = $DEFAULT_BRANCH):"
81
- read -r bp
82
- BRANCH_PREFIX="${bp:-$DEFAULT_BRANCH}"
83
- echo " → branch_prefix: $BRANCH_PREFIX(project.json に反映)"
84
- else
85
- BRANCH_PREFIX="$DEFAULT_BRANCH"
86
- fi
87
- # UC 以外の作業用ブランチ接頭辞(feature/<接頭辞>/xxx)
88
- DEFAULT_OTHER_WORK="work, infra, cicd"
89
- if [[ -f "$CONFIG" ]]; then
90
- current_ow=$(jq -r '.naming.other_work_prefixes | join(", ") // empty' "$CONFIG" 2>/dev/null)
91
- [[ -n "$current_ow" ]] && DEFAULT_OTHER_WORK="$current_ow"
92
- fi
93
- echo " UC 以外の作業用ブランチ接頭辞(カンマ区切り。例: feature/cicd/xxx, feature/infra/xxx)"
94
- echo " 現在: [$DEFAULT_OTHER_WORK]"
95
- echo " 変更する場合は入力、そのままなら Enter:"
96
- read -r other_work_input
97
- if [[ -n "$other_work_input" ]]; then
98
- OTHER_WORK_JSON=$(echo "$other_work_input" | jq -R 'split(",") | map(gsub("^ +| +$";"")) | map(select(length>0))')
99
- echo " → other_work_prefixes を反映します"
100
- else
101
- OTHER_WORK_JSON=""
102
- fi
103
- echo ""
104
-
105
- # --- 3. 設計書チェック(必須ドキュメント)---
106
- echo "【3】設計書チェック(ゲート確認で必須とするドキュメント一覧)"
107
- CREATE_OR_UPDATE=""
108
- if [[ -f "$CONFIG" ]]; then
109
- echo " 現在の project.json の required_docs を使用します。"
110
- # naming.branch_prefix / other_work_prefixes / test_command.run を今回の値で更新
111
- jq --arg bp "$BRANCH_PREFIX" '.naming.branch_prefix = $bp' "$CONFIG" > "${CONFIG}.tmp" 2>/dev/null && mv "${CONFIG}.tmp" "$CONFIG"
112
- if [[ -n "$OTHER_WORK_JSON" ]]; then
113
- jq --argjson ow "$OTHER_WORK_JSON" '.naming.other_work_prefixes = $ow' "$CONFIG" > "${CONFIG}.tmp" 2>/dev/null && mv "${CONFIG}.tmp" "$CONFIG"
114
- fi
115
- if [[ -n "$RUN_CMD" ]]; then
116
- jq --arg run "$RUN_CMD" '.test_command = {run: $run}' "$CONFIG" > "${CONFIG}.tmp" 2>/dev/null && mv "${CONFIG}.tmp" "$CONFIG"
117
- echo " → test_command と naming を反映しました: $RUN_CMD"
118
- else
119
- echo " 命名(branch_prefix / other_work_prefixes)を反映しました。編集は .spec-runner/project.json を直接変更してください。"
120
- fi
121
- else
122
- echo " project.json がありません。デフォルトの必須ドキュメントで作成しますか? (Y/n)"
123
- read -r create_docs
124
- if [[ "$create_docs" != "n" && "$create_docs" != "N" ]]; then
125
- CREATE_OR_UPDATE=1
126
- mkdir -p "$SPEC_RUNNER"
127
- if [[ -f "$SPEC_RUNNER/project.json.example" ]]; then
128
- cp "$SPEC_RUNNER/project.json.example" "$CONFIG"
129
- jq --arg bp "$BRANCH_PREFIX" '.naming.branch_prefix = $bp' "$CONFIG" > "${CONFIG}.tmp" && mv "${CONFIG}.tmp" "$CONFIG"
130
- [[ -n "$OTHER_WORK_JSON" ]] && jq --argjson ow "$OTHER_WORK_JSON" '.naming.other_work_prefixes = $ow' "$CONFIG" > "${CONFIG}.tmp" && mv "${CONFIG}.tmp" "$CONFIG"
131
- if [[ -n "$RUN_CMD" ]]; then
132
- jq --arg run "$RUN_CMD" '.test_command = {run: $run}' "$CONFIG" > "${CONFIG}.tmp" && mv "${CONFIG}.tmp" "$CONFIG"
133
- fi
134
- echo " → project.json をデフォルトで作成しました。"
135
- else
136
- ow_default='["work","infra","cicd"]'
137
- [[ -n "$OTHER_WORK_JSON" ]] && ow_default="$OTHER_WORK_JSON"
138
- jq -n \
139
- --arg bp "$BRANCH_PREFIX" \
140
- --arg run "${RUN_CMD:-npm test}" \
141
- --argjson ow "$ow_default" \
142
- '{naming: {branch_prefix: $bp, uc_id_pattern: "UC-[0-9]{3}", uc_spec_basename: "{uc_id}-{slug}.md", adr_basename: "MMDD-{title}.md", docs_05_categories: true, other_work_prefixes: $ow}, required_docs: {charter: ["docs/01_憲章/憲章.md"], domain: ["docs/02_ドメイン設計/ユビキタス言語辞書.md", "docs/02_ドメイン設計/ドメインモデル.md", "docs/02_ドメイン設計/集約.md"], architecture: ["docs/03_アーキテクチャ/パターン選定.md", "docs/03_アーキテクチャ/インフラ方針.md", "docs/03_アーキテクチャ/設計判断記録"], grade_a: ["docs/04_インフラ設計/schema.dbml"], gate3_openapi: ["docs/06_API仕様/openapi.yaml"]}, test_design: {dir: "tests", pattern: "*.spec.*"}, test_command: {run: $run}}' \
143
- > "$CONFIG"
144
- echo " → project.json を作成しました。"
145
- fi
146
- fi
147
- fi
148
- echo ""
149
-
150
- echo "=== 初期設定の流れは以上です ==="
151
- echo " 再実行: .spec-runner/scripts/setup/init-project.sh"
152
- echo " 設定の編集: .spec-runner/project.json(1 ファイルに集約)"