spec-runner 1.0.18 → 1.0.22

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 CHANGED
@@ -18,6 +18,14 @@ curl -sSL https://raw.githubusercontent.com/TEEE88/spec-runner/main/install.sh |
18
18
 
19
19
  いずれも、プロジェクト直下に `.spec-runner/` ができる。
20
20
 
21
+ あわせて、**未有効時のみ**プロジェクトルートに次が配置される(Material for MkDocs で `docs/` 配下の設計書をプレビューするため)。
22
+
23
+ - `mkdocs.yml` / `requirements-docs.txt`
24
+ - `docs/index.md`(サイトのホーム)
25
+ - `docs/spec-runner-フロー.md`(`spec-runner` パッケージ同梱の手順書)
26
+
27
+ `.spec-runner/` がすでにあり **2 回目以降はエラーで止まる** 場合も、**その手前**で上記 MkDocs 用ファイルの不足分だけ補完される(初回導入以前のリポジトリで MkDocs だけ足したいときに便利)。
28
+
21
29
  ---
22
30
 
23
31
  ## 使い方
@@ -42,6 +50,24 @@ AI から使う場合は、`/spec-runner` のように「spec-runner を実行
42
50
 
43
51
  ---
44
52
 
53
+ ## ドキュメントサイト(MkDocs + Material)
54
+
55
+ ### `npx spec-runner` したプロジェクト側
56
+
57
+ 憲章・設計書は `steps.json` どおり `docs/01_憲章/` 〜 `docs/06_API仕様/` に置かれる。`mkdocs.yml` の `docs/` がそのままサイトの文書ルートになるので、**追加コピーなしで**これらの Markdown をナビに載せられる(`nav` で先頭に固定した `index.md` の後ろへ、残りのページが自動で続く)。
58
+
59
+ プレビュー起動(Python 3 必須・仮想環境 `.venv-docs/` を使用):
60
+
61
+ ```bash
62
+ ./.spec-runner/scripts/docs-serve.sh
63
+ ```
64
+
65
+ `8000` が使用中のとき:
66
+
67
+ ```bash
68
+ DOCS_PORT=8001 ./.spec-runner/scripts/docs-serve.sh
69
+ ```
70
+
45
71
  ## 導入後にできるもの
46
72
 
47
73
  ```
@@ -51,10 +77,13 @@ AI から使う場合は、`/spec-runner` のように「spec-runner を実行
51
77
  │ ├── project.json # 設定(ブランチ命名・必須ドキュメント・テストコマンド等)
52
78
  │ ├── phase-locks.json # フェーズの通過状態
53
79
  │ ├── grade-history.json # グレード(LOOP1 / A / B / C)
54
- │ ├── scripts/ # spec-runner-core.sh, check, branch, test
80
+ │ ├── scripts/ # spec-runner-core.sh, check, branch, docs-serve.sh
55
81
  │ ├── steps/ # 憲章・ドメイン設計・仕様策定・曖昧さ解消・テスト設計・実装 等の .md
56
82
  │ └── templates/ # UC 仕様書ひな形
57
83
  ├── .claude/commands/spec-runner.md # Claude 用コマンド定義(/spec-runner)
84
+ ├── mkdocs.yml # MkDocs(未有効時のみ配置)
85
+ ├── requirements-docs.txt # mkdocs / mkdocs-material(未有効時のみ配置)
86
+ ├── docs/ # 設計書(01..06)+ index.md 等。MkDocs の文書ルート
58
87
  └── (AI は Claude Code 前提)
59
88
  ```
60
89
 
@@ -66,6 +95,7 @@ AI から使う場合は、`/spec-runner` のように「spec-runner を実行
66
95
  - jq
67
96
  - git
68
97
  - bash 4.0+
98
+ - 設計書の MkDocs プレビュー: Python 3(`docs-serve.sh` が `python3` と venv を使用)
69
99
 
70
100
  ---
71
101
 
@@ -19,6 +19,11 @@
19
19
  * - templates/.spec-runner/project.json.example
20
20
  * - templates/.spec-runner/templates/phase-locks.json
21
21
  * - templates/.spec-runner/templates/grade-history.json
22
+ *
23
+ * MkDocs(任意・プロジェクトルート):
24
+ * - templates/mkdocs-scaffold/ の mkdocs.yml / requirements-docs.txt / docs/index.md を
25
+ * 未有効時のみコピー(憲章・設計書は既存の docs/01..06 をそのまま閲覧)
26
+ * - パッケージ同梱の docs/flow.md を docs/spec-runner-フロー.md としてコピー(未存在時のみ)
22
27
  */
23
28
 
24
29
  const fs = require("fs");
@@ -31,6 +36,8 @@ const DEST_DIR = path.join(CWD, ".spec-runner");
31
36
  const TEMPLATES_DIR = path.join(TEMPLATE_SPEC_RUNNER_DIR, "templates");
32
37
  const PHASE_LOCKS_TEMPLATE = path.join(TEMPLATES_DIR, "phase-locks.json");
33
38
  const GRADE_HISTORY_TEMPLATE = path.join(TEMPLATES_DIR, "grade-history.json");
39
+ const MKDOCS_SCAFFOLD_DIR = path.join(PKG_DIR, "templates", "mkdocs-scaffold");
40
+ const FLOW_DOC_SRC = path.join(PKG_DIR, "docs", "flow.md");
34
41
 
35
42
  /** コピー時はスキップし、FORCE 時は消さない(ユーザー状態を保持) */
36
43
  const USER_STATE_BASENAMES = new Set([
@@ -170,6 +177,57 @@ function installClaudeCommandIfPresent() {
170
177
  ok(path.relative(CWD, claudeCmd));
171
178
  }
172
179
 
180
+ /**
181
+ * MkDocs + Material 用のファイルをプロジェクトルートに配置(未存在時のみ)。
182
+ * 設計書本体は steps.json どおり docs/01..06 に置かれ、mkdocs の docs_dir でそのまま掲載する。
183
+ */
184
+ function copyFileIfMissing(src, dest) {
185
+ if (!exists(src) || exists(dest)) return false;
186
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
187
+ fs.copyFileSync(src, dest);
188
+ ok(path.relative(CWD, dest));
189
+ return true;
190
+ }
191
+
192
+ function appendGitignoreVenvDocsIfNeeded() {
193
+ const gitignorePath = path.join(CWD, ".gitignore");
194
+ const marker = ".venv-docs/";
195
+ if (!exists(gitignorePath)) return;
196
+ const raw = fs.readFileSync(gitignorePath, "utf8");
197
+ const lines = raw.split(/\r?\n/);
198
+ if (lines.some((line) => /^\.venv-docs\/?$/.test(line.trim()))) return;
199
+ fs.appendFileSync(
200
+ gitignorePath,
201
+ `\n# spec-runner: MkDocs 用 Python 仮想環境\n${marker}\n`,
202
+ "utf8",
203
+ );
204
+ ok(`${path.relative(CWD, gitignorePath)}(${marker} を追記)`);
205
+ }
206
+
207
+ function installMkdocsScaffold() {
208
+ if (!exists(MKDOCS_SCAFFOLD_DIR)) {
209
+ info("MkDocs テンプレート(templates/mkdocs-scaffold)が見つかりません。スキップします。");
210
+ return;
211
+ }
212
+ info("MkDocs 用ファイル(不足分のみ)をプロジェクトルートに配置します...");
213
+ copyFileIfMissing(
214
+ path.join(MKDOCS_SCAFFOLD_DIR, "mkdocs.yml"),
215
+ path.join(CWD, "mkdocs.yml"),
216
+ );
217
+ copyFileIfMissing(
218
+ path.join(MKDOCS_SCAFFOLD_DIR, "requirements-docs.txt"),
219
+ path.join(CWD, "requirements-docs.txt"),
220
+ );
221
+ copyFileIfMissing(
222
+ path.join(MKDOCS_SCAFFOLD_DIR, "docs", "index.md"),
223
+ path.join(CWD, "docs", "index.md"),
224
+ );
225
+ if (exists(FLOW_DOC_SRC)) {
226
+ copyFileIfMissing(FLOW_DOC_SRC, path.join(CWD, "docs", "spec-runner-フロー.md"));
227
+ }
228
+ appendGitignoreVenvDocsIfNeeded();
229
+ }
230
+
173
231
  function printBanner() {
174
232
  log("");
175
233
  log("╔════════════════════════════════════════╗");
@@ -180,6 +238,9 @@ function printBanner() {
180
238
  }
181
239
 
182
240
  function printFooter() {
241
+ log("");
242
+ log("設計書プレビュー(MkDocs + Material・プロジェクトルートの docs/):");
243
+ log(" ./.spec-runner/scripts/docs-serve.sh");
183
244
  log("");
184
245
  log("次のステップ(Claude Code 専用):");
185
246
  log(" /spec-runner を実行して");
@@ -189,6 +250,7 @@ function printFooter() {
189
250
  function main() {
190
251
  printBanner();
191
252
  ensureTemplateDirOrExit();
253
+ installMkdocsScaffold();
192
254
  assertDestInstallableOrExit();
193
255
 
194
256
  info(".spec-runner/ を展開しています...");
package/docs/flow.md ADDED
@@ -0,0 +1,213 @@
1
+ # spec-runner の進め方(実装準拠)
2
+
3
+ このドキュメントは **リポジトリ内の実装**(`templates/.spec-runner/scripts/spec-runner-core.sh`、`steps/steps.json` 等)に沿って書いています。
4
+ 「次のステップ」は **1 本のコマンド**が返す **1 つの `command_file`(`.spec-runner/steps/*.md`)** だけです。
5
+
6
+ ---
7
+
8
+ ## 入口コマンド(毎回)
9
+
10
+ | 用途 | コマンド(プロジェクトルート) |
11
+ |------|-------------------------------|
12
+ | 次のステップ(人間向けテキスト) | `./.spec-runner/spec-runner.sh` または `./.spec-runner/spec-runner.sh 次のステップ` |
13
+ | 次のステップ(JSON) | `./.spec-runner/spec-runner.sh 次のステップ --json` |
14
+ | Lock 一覧 | `./.spec-runner/spec-runner.sh 次のステップ --lock`(内部では `--status`) |
15
+ | グレード判定ガイド | `./.spec-runner/spec-runner.sh 次のステップ --グレード` |
16
+
17
+ - **やること**: 出力の `command_file` を開き、その `.md` の指示どおりに作業する。
18
+ - **毎回の検証**: `steps.json` の `common.commands.check` → 既定は `.spec-runner/scripts/check.sh`。
19
+
20
+ ### `--json` の主なフィールド(実装どおり)
21
+
22
+ | フィールド | 意味 |
23
+ |------------|------|
24
+ | `phase` | 数値(`steps.json` の各 step の `phase` と概ね対応) |
25
+ | `phase_name_ja` | 表示用ラベル(コアが付与) |
26
+ | `step_id` | `steps.json` の `id`(例: `charter`, `uc_spec`, `clarify`) |
27
+ | `command` | ステップの日本語名(`name_ja`) |
28
+ | `command_file` | 絶対パス想定の `.spec-runner/steps/<md_file>` |
29
+ | `grade` | `grade-history.json` の `current_grade` |
30
+ | `check_command` | 毎回のチェック用シェルコマンド |
31
+ | `step_commands` | そのステップ用のコマンド配列(JSON) |
32
+ | `feature_dir` / `feature_spec` | UC ブランチ時、該当 UC のディレクトリ・仕様書パス(取れれば) |
33
+
34
+ ---
35
+
36
+ ## 状態の単一ソース
37
+
38
+ ### `.spec-runner/phase-locks.json`
39
+
40
+ 実際のキーは次のとおり(各オブジェクトに `completed`, `locked_at`, `reviewed_by` 等)。
41
+
42
+ | キー | 意味 |
43
+ |------|------|
44
+ | `charter` | 憲章フェーズ完了。ゲートでは `reviewed_by` も参照(LOOP1 時) |
45
+ | `domain` | ドメイン設計フェーズ完了 |
46
+ | `architecture` | アーキ(実装計画)フェーズ完了 |
47
+ | `infra` | インフラ詳細(Grade A)完了 |
48
+ | `test_design` | テスト設計ロック(ゲート側で参照) |
49
+ | `uc_discovery` | UC 洗い出し完了(`false` の間は domain に進まない) |
50
+ | `uc_reviewed` | **文字列の配列**。UC 仕様ファイルの **ベース名(拡張子なし)** が入ると「レビュー通過」とみなす(例: `UC-1-foo`) |
51
+
52
+ ### `.spec-runner/grade-history.json`
53
+
54
+ - `current_grade`: `LOOP1` / `A` / `B` / `C` など(**ブランチ名には含めない**)
55
+ - Grade A のとき、UC レビュー通過後は **インフラ詳細(`infra_plan`)** が先に出る(`infra.completed` が付くまで)
56
+
57
+ ### `.spec-runner/project.json`
58
+
59
+ - `naming`: ブランチ接頭辞 `branch_prefix`(既定 `feature`)、`uc_id_pattern`、`other_work_prefixes`(例: `work`, `infra`, `cicd`)
60
+ - `required_docs`: ゲート確認時の必須パス(`steps:charter` 形式で `steps.json` の `common.docs` を参照)
61
+ - `test_design.dir` / `test_design.pattern`(既定: `tests`, `*.spec.*`)
62
+ - `test_design.require_uc_prefixed_tests`(既定: キー省略時 **true**): **TDD 前提**。UC ブランチでは **`UC-N-` で始まり `pattern` に合致するテストファイル**が `test_design.dir` 内に無い限り **`test_design` のまま**(`implement` に進めない)。`false` にすると従来どおり「任意の spec が1つでもあれば実装」。
63
+ - `test_command.run`: **`require-tests-green.sh` が実行するテストコマンド**(実装完了の機械的条件)
64
+
65
+ ---
66
+
67
+ ## 「次のステップ」の分岐(`spec-runner-core.sh` の実際)
68
+
69
+ ブランチ種別・ロック・UC 有無・`uc_reviewed`・グレード・テストファイル有無で決まります。**紙の上の「常に UC→ドメイン→アーキ」の直線とは一致しません。**
70
+
71
+ ### 1) UC ブランチ上(`feature/<UC-N>-<slug>` 形式)
72
+
73
+ 1. 該当 `UC-N-*.md` が **まだ無い** → **`uc_spec`**(仕様策定)
74
+ 2. 仕様はあるが **`uc_reviewed` にベース名が無い** → **`clarify`**(曖昧さ解消・レビュー通過まで)
75
+ 3. レビュー済みかつ **`uc_discovery.completed` が false** → **`uc_spec`**(次UC作成)
76
+ 4. レビュー済みかつ **Grade A かつ `infra.completed` でない** → **`infra_plan`**
77
+ 5. それ以外で **当該 UC 用テストが未準備**(`require_uc_prefixed_tests` が true のときは **`UC-N-*.spec.*` 形式が1つ以上**)→ **`test_design`**
78
+ 6. 上記を満たす → **`implement`**(あわせて **テストがグリーン**になるまで完了とみなさないのは `require-tests-green.sh` 側)
79
+
80
+ ※ **ドメイン・アーキのロック未完了でも**、上記 UC ブランチ上では 3〜6 に進めます(コア実装どおり)。
81
+
82
+ ### 2) UC ブランチではない(main 等)
83
+
84
+ 実装では **次の順で最初に当てはまる分岐**が選ばれます(UC ブランチでも `other_work` ブランチでもない場合)。
85
+
86
+ 1. **`charter.completed` でない**
87
+ - `docs/01_憲章/憲章.md` が無い → **`charter`**
88
+ - `docs/01_憲章/憲章.md` があり、`quality.clarified.charter` 未記録 → **`clarify`**(憲章の曖昧さ解消)
89
+ - `docs/01_憲章/憲章.md` があり、`quality.analyzed.charter` 未記録 → **`analyze`**(憲章の分析)
90
+ - 上記が記録済み → **`charter`**
91
+ 2. **ドメイン未ロックかつ `uc_discovery.completed` が false** → **`uc_spec`**(次UC作成)
92
+ 3. **ドメイン未ロックかつ `uc_discovery.completed` が true かつ `docs/02_...` に UC が 1 件以上**
93
+ - `docs/03_ドメイン設計/` に `.md` があり、`quality.clarified.domain` 未記録 → **`clarify`**
94
+ - `docs/03_ドメイン設計/` に `.md` があり、`quality.analyzed.domain` 未記録 → **`analyze`**
95
+ - 上記が記録済み、または `.md` が無い → **`domain`**
96
+ 4. **ドメイン済みかつアーキ未ロック**
97
+ - `docs/04_アーキテクチャ/` に `.md` があり、`quality.clarified.architecture` 未記録 → **`clarify`**
98
+ - `docs/04_アーキテクチャ/` に `.md` があり、`quality.analyzed.architecture` 未記録 → **`analyze`**
99
+ - 上記が記録済み、または `.md` が無い → **`architecture_plan`**
100
+ 5. **`other_work` 用ブランチ**(`feature/<other_work_prefix>/...`)かつ **2〜4 を通過済み** → **`other_work`**
101
+ 6. **ドメイン未ロック**(この時点では UC が 0 件)→ **`uc_spec`**
102
+ 7. **ドメイン・アーキともロック済み** → **`uc_spec`**(次の UC 開始)
103
+
104
+ 要点:
105
+
106
+ - **初回**: main で UC がまだ無いと **6** で **`uc_spec`**。
107
+ - **UC がリポジトリに既にあるのにドメイン未ロック**(main で作業)→ `uc_discovery.completed=false` の間は **`uc_spec`** が先(`true` になってから **`domain`**)。
108
+ - **アーキ**は **ドメイン完了後**に **4** で出る。
109
+
110
+ ### 3) 自動では選ばれないステップ(`steps.json` にのみ存在)
111
+
112
+ 次の `id` は **コアの `run_phase` では返しません**。各 `.md`(仕様策定・テスト設計等)の **手順の中で**使う想定です。
113
+
114
+ - `analyze`(分析)
115
+ - `checklist`(チェックリスト)
116
+ - `task_list`(タスク一覧)
117
+
118
+ ---
119
+
120
+ ## 成果物の置き場所(`steps.json` の `common.docs` と一致)
121
+
122
+ | キー | パス(既定) |
123
+ |------|----------------|
124
+ | 憲章 | `docs/01_憲章/憲章.md` |
125
+ | UC ルート | `docs/02_ユースケース仕様/<カテゴリ>/UC-N-<slug>.md` |
126
+ | ドメイン | `docs/03_ドメイン設計/`(ユビキタス言語辞書・ドメインモデル・集約 等) |
127
+ | アーキ | `docs/04_アーキテクチャ/` |
128
+ | インフラ | `docs/05_インフラ設計/`(例: `schema.dbml`) |
129
+ | API | `docs/06_API仕様/openapi.yaml` |
130
+
131
+ - UC ファイル名は **`UC-<N>-<slug>.md`**(`slug` は英数字・ハイフンが無難。ブランチ名も ASCII)。
132
+ - カテゴリフォルダ名は日本語可。
133
+
134
+ ---
135
+
136
+ ## ディレクトリ構成(パッケージテンプレに近い形)
137
+
138
+ ```
139
+ <プロジェクトルート>/
140
+ ├── .spec-runner/
141
+ │ ├── spec-runner.sh
142
+ │ ├── project.json # 初回は project.json.example から
143
+ │ ├── phase-locks.json # 初回は templates/phase-locks.json から
144
+ │ ├── grade-history.json
145
+ │ ├── scripts/
146
+ │ │ ├── spec-runner-core.sh
147
+ │ │ ├── check.sh # --every / --full
148
+ │ │ ├── branch/uc-next-start.sh
149
+ │ │ └── test/require-tests-green.sh
150
+ │ ├── steps/ # *.md + steps.json
151
+ │ ├── templates/ # 憲章・UC・ドメイン雛形等
152
+ │ └── hooks/ # pre-commit / pre-push(任意)
153
+ ├── docs/01_憲章/ … 06_API仕様/
154
+ ├── tests/ # project.json の test_design.dir
155
+ └── src/
156
+ ```
157
+
158
+ - **`npx spec-runner`**: `.spec-runner/` を展開し、**`.claude/commands/spec-runner.md` を配置**(テンプレに存在する場合)。`.cursor/` への自動配置は **インストーラでは行っていない**。
159
+
160
+ ---
161
+
162
+ ## フェーズ番号とステップ(`steps.json`)
163
+
164
+ | phase | step_id(代表) | 内容 |
165
+ |-------|-----------------|------|
166
+ | 0 | `charter` | 憲章 |
167
+ | 1 | `uc_spec` / `other_work` | UC 仕様・その他ブランチ |
168
+ | 2 | `domain` | ドメイン設計 |
169
+ | 3 | `architecture_plan` | 実装計画(アーキ) |
170
+ | 4 | `infra_plan` | インフラ詳細(Grade A) |
171
+ | 5 | `test_design` | PENDING テスト |
172
+ | 6 | `implement` | 実装・テストグリーン |
173
+
174
+ `clarify`(曖昧さ解消)と `analyze`(分析)は `phase: null` の任意ステップとして扱い、必要なタイミングで実行できます。
175
+
176
+ 補足: `clarify` / `analyze` の自動実行は `.spec-runner/phase-locks.json` の `quality` によって 1 度ずつ管理します。
177
+ (UC は `uc_reviewed` 未登録の間、`clarify -> analyze -> clarify ...` の品質ループを回せます)
178
+
179
+ ### 実装完了(Phase 6)の機械的条件
180
+
181
+ - **手動または CI で** `.spec-runner/scripts/test/require-tests-green.sh` が **exit 0** であること。
182
+ - 中身は `project.json` の **`test_command.run`** のみを `eval` 実行(例: `npm test`)。
183
+
184
+ ### ゲート(`spec-runner-core.sh --gate`)のメモ
185
+
186
+ ゲートログ上の「Phase 1/2」表現は **ドメイン=Phase 1、アーキ=Phase 2** のように **steps.json の phase 番号と一致しません**。ロック対象は `phase-locks.json` のキーで判断してください。
187
+
188
+ ---
189
+
190
+ ## TDD が「どこまで」強制されるか
191
+
192
+ | レベル | 内容 |
193
+ |--------|------|
194
+ | **ゲート(次のステップ)** | 上記どおり **先に当該 UC の spec ファイルを置く**まで `implement` を出さない(`require_uc_prefixed_tests: true` 時)。 |
195
+ | **レッド→グリーンの順序** | **コミット順や「本番コードより先にアサーションを書いたか」は機械検査していない**。Phase 5 で PENDING/skip、Phase 6 で実装・グリーン、という **フェーズ順**での強制。 |
196
+ | **完了条件** | `require-tests-green.sh`(`test_command.run` 全通過)。 |
197
+
198
+ ---
199
+
200
+ ## 理想運用 vs コードのギャップ(把握用)
201
+
202
+ | 観点 | よく言われる理想 | 実コード |
203
+ |------|------------------|----------|
204
+ | UC とドメインの順序 | 常に UC 全部 → ドメイン | `uc_discovery.completed=false` の間は次UC(`uc_spec`)→ `true` になってから domain |
205
+ | UC 実装前にアーキ必須 | あり | **UC ブランチ上では**ドメイン・アーキ未ロックでもテスト設計・実装に進む |
206
+
207
+ 運用で「必ずドメイン→アーキ→UC 実装」にしたい場合は、**ロックを先に済ませてから** UC ブランチに入る、またはコアの分岐変更が必要です。
208
+
209
+ ---
210
+
211
+ ## 日本語ドキュメント
212
+
213
+ `docs/` 配下の設計書は日本語で問題ありません。**Git 上はブランチ名・UC ファイルの slug は ASCII(kebab-case)推奨**です。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-runner",
3
- "version": "1.0.18",
3
+ "version": "1.0.22",
4
4
  "description": "フェーズ駆動で設計先行を強制。npx で .spec-runner を展開し、次のステップ .md に従って進める",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -26,6 +26,7 @@
26
26
  "files": [
27
27
  "bin/",
28
28
  "templates/",
29
+ "docs/flow.md",
29
30
  "install.sh",
30
31
  "README.md",
31
32
  "LICENSE"
@@ -318,10 +318,11 @@ run_health_check() {
318
318
  for f in "$UC_ROOT"/*/UC-*.md; do
319
319
  [[ -f "$f" ]] || continue
320
320
  base=$(basename "$f" .md)
321
- if ! grep -qE '受入条件|成功基準|前提:|操作:|期待:|\\|[[:space:]]*前提[[:space:]]*\\|[[:space:]]*操作[[:space:]]*\\|[[:space:]]*期待[[:space:]]*\\|' "$f" 2>/dev/null; then
321
+ # 表ヘッダ(例: `| 前提 | 操作 | 期待 |`)の `|` は `\|` としてリテラル扱いする
322
+ if ! grep -qE '受入条件|成功基準|前提:|操作:|期待:|\|[[:space:]]*前提[[:space:]]*\|[[:space:]]*操作[[:space:]]*\|[[:space:]]*期待[[:space:]]*\|' "$f" 2>/dev/null; then
322
323
  drifts+=("UC ${base}: 受入条件または成功基準がありません")
323
324
  fi
324
- count=$(grep -c '\\[要確認:' "$f" 2>/dev/null || echo 0)
325
+ count=$(grep -c '\[要確認:' "$f" 2>/dev/null || echo 0)
325
326
  count=$(echo "$count" | head -1 | tr -cd '0-9'); count=${count:-0}
326
327
  [[ "$count" -gt 3 ]] && drifts+=("UC ${base}: [要確認: が ${count} 個(3個以下にすること)")
327
328
  # `## 実装方針` / `## タスク(一覧)` は実装計画以降で埋まる想定。
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+ # MkDocs + Material で docs/ をプレビュー(プロジェクトルートで実行される想定)
3
+ set -euo pipefail
4
+
5
+ ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
6
+ cd "$ROOT"
7
+
8
+ DOCS_PORT="${DOCS_PORT:-8000}"
9
+ REQ="requirements-docs.txt"
10
+
11
+ if [[ ! -f "$REQ" ]]; then
12
+ echo "ERROR: ${REQ} が見つかりません。npx spec-runner を実行して MkDocs 用ファイルを展開してください。" >&2
13
+ exit 1
14
+ fi
15
+
16
+ if [[ ! -d .venv-docs ]]; then
17
+ python3 -m venv .venv-docs
18
+ fi
19
+
20
+ ./.venv-docs/bin/pip install -q -r "$REQ"
21
+ exec ./.venv-docs/bin/mkdocs serve --dev-addr "127.0.0.1:${DOCS_PORT}"
@@ -71,6 +71,7 @@ has_charter_lock=0
71
71
  has_domain_lock=0
72
72
  has_arch_lock=0
73
73
  has_infra_lock=0
74
+ uc_discovery_completed=0
74
75
  grade=""
75
76
  branch=""
76
77
  test_dir=""
@@ -87,6 +88,7 @@ load_state() {
87
88
  jq -e '.domain.completed == true' "$LOCK_FILE" >/dev/null 2>&1 && has_domain_lock=1
88
89
  jq -e '.architecture.completed == true' "$LOCK_FILE" >/dev/null 2>&1 && has_arch_lock=1
89
90
  jq -e '.infra.completed == true' "$LOCK_FILE" >/dev/null 2>&1 && has_infra_lock=1
91
+ jq -e '.uc_discovery.completed == true' "$LOCK_FILE" >/dev/null 2>&1 && uc_discovery_completed=1
90
92
 
91
93
  grade=$(jq -r '.current_grade' "$GRADE_FILE")
92
94
  [[ -n "$grade" && "$grade" != "null" ]] || die "spec-runner-core: grade-history.json の current_grade が未設定です"
@@ -328,21 +330,31 @@ run_phase() {
328
330
  else
329
331
  phase=0; phase_name_ja="憲章策定"; resolve_step "charter"
330
332
  fi
331
- elif [[ $has_domain_lock -eq 0 && ${uc_count_total} -gt 0 && $on_uc_branch -eq 0 ]]; then
332
- domain_spec="$(first_md_in_dir "$domain_root" || true)"
333
- if [[ -n "$domain_spec" ]]; then
334
- feature_spec="$domain_spec"
335
- feature_dir="$(dirname "$domain_spec")"
336
- dkey="$(doc_key "$domain_spec")"
337
- if ! quality_done "clarified" "domain" "$dkey"; then
338
- phase=2; phase_name_ja="ドメイン設計(曖昧さ解消)"; resolve_step "clarify"
339
- elif ! quality_done "analyzed" "domain" "$dkey"; then
340
- phase=2; phase_name_ja="ドメイン設計(分析)"; resolve_step "analyze"
333
+ elif [[ $has_domain_lock -eq 0 && $on_uc_branch -eq 0 ]]; then
334
+ # UC を洗い出している途中(uc_discovery.completed=false)の間はドメインへ進まない
335
+ if [[ $uc_discovery_completed -eq 0 ]]; then
336
+ phase=1; phase_name_ja="ユースケース洗い出し中(次UC作成)"; resolve_step "uc_spec"
337
+ else
338
+ # UC が 1 件以上ある場合のみ、ドメイン側の質フローを回す
339
+ if [[ ${uc_count_total} -gt 0 ]]; then
340
+ domain_spec="$(first_md_in_dir "$domain_root" || true)"
341
+ if [[ -n "$domain_spec" ]]; then
342
+ feature_spec="$domain_spec"
343
+ feature_dir="$(dirname "$domain_spec")"
344
+ dkey="$(doc_key "$domain_spec")"
345
+ if ! quality_done "clarified" "domain" "$dkey"; then
346
+ phase=2; phase_name_ja="ドメイン設計(曖昧さ解消)"; resolve_step "clarify"
347
+ elif ! quality_done "analyzed" "domain" "$dkey"; then
348
+ phase=2; phase_name_ja="ドメイン設計(分析)"; resolve_step "analyze"
349
+ else
350
+ phase=2; phase_name_ja="ドメイン設計"; resolve_step "domain"
351
+ fi
352
+ else
353
+ phase=2; phase_name_ja="ドメイン設計"; resolve_step "domain"
354
+ fi
341
355
  else
342
- phase=2; phase_name_ja="ドメイン設計"; resolve_step "domain"
356
+ phase=1; phase_name_ja="ユースケース洗い出し中(次UC作成)"; resolve_step "uc_spec"
343
357
  fi
344
- else
345
- phase=2; phase_name_ja="ドメイン設計"; resolve_step "domain"
346
358
  fi
347
359
  elif [[ $has_arch_lock -eq 0 && $has_domain_lock -eq 1 ]]; then
348
360
  arch_spec="$(first_md_in_dir "$architecture_root" || true)"
@@ -382,7 +394,10 @@ run_phase() {
382
394
  phase=1; phase_name_ja="ユースケース仕様(レビュー通過まで)"; resolve_step "clarify"
383
395
  fi
384
396
  else
385
- if [[ "$grade" == "A" ]] && [[ $has_infra_lock -eq 0 ]]; then
397
+ # UC 洗い出し中は、レビュー済みでも次の UC 作成へ戻す(TDD/実装に進まない)
398
+ if [[ $uc_discovery_completed -eq 0 ]]; then
399
+ phase=1; phase_name_ja="ユースケース洗い出し中(次UC作成)"; resolve_step "uc_spec"
400
+ elif [[ "$grade" == "A" ]] && [[ $has_infra_lock -eq 0 ]]; then
386
401
  phase=4; phase_name_ja="インフラ詳細設計"; resolve_step "infra_plan"
387
402
  else
388
403
  if uc_branch_has_tests_ready_for_implement; then
@@ -429,7 +444,7 @@ run_status() {
429
444
  echo "グレード: $grade"
430
445
  echo ""
431
446
  echo "Lock(.spec-runner/phase-locks.json):"
432
- for sec in charter domain architecture infra test_design; do
447
+ for sec in charter domain architecture infra uc_discovery test_design; do
433
448
  if jq -e --arg s "$sec" '.[$s].completed == true' "$LOCK_FILE" >/dev/null 2>&1; then
434
449
  echo " ✓ $sec"
435
450
  else
@@ -99,6 +99,8 @@ checklists を使う場合のみ `FEATURE_DIR/checklists/requirements.md` を生
99
99
 
100
100
  ※ 分解提案を経た場合は、採用された UC 分割案(採用順)も合わせて報告する。
101
101
 
102
+ ※ **UC 洗い出しが完了したら** `./.spec-runner/phase-locks.json` の `uc_discovery.completed` を `true` にする(以降 `domain` に進む)。
103
+
102
104
  **注**: スクリプトは書き込み前にブランチ作成・チェックアウトと仕様の初期化を行う。
103
105
 
104
106
  ## 付録 A: 仕様品質チェックリスト例
@@ -25,6 +25,11 @@
25
25
  "locked_at": null,
26
26
  "reviewed_by": null
27
27
  },
28
+ "uc_discovery": {
29
+ "completed": false,
30
+ "locked_at": null,
31
+ "reviewed_by": null
32
+ },
28
33
  "uc_reviewed": [],
29
34
  "quality": {
30
35
  "_comment": "clarify/analyze の実行済み管理(対象ドキュメントのベース名)",
@@ -0,0 +1,32 @@
1
+ # 設計ドキュメント
2
+
3
+ このサイトは **MkDocs Material** で、プロジェクトの `docs/` 配下にある **憲章・設計書・仕様** をまとめて閲覧するためのものです。
4
+
5
+ ## spec-runner との対応(既定パス)
6
+
7
+ | 領域 | パス(プロジェクトルートから) |
8
+ |------|------------------------------|
9
+ | 憲章 | `docs/01_憲章/憲章.md` |
10
+ | ユースケース仕様 | `docs/02_ユースケース仕様/` |
11
+ | ドメイン設計 | `docs/03_ドメイン設計/` |
12
+ | アーキテクチャ | `docs/04_アーキテクチャ/` |
13
+ | インフラ設計 | `docs/05_インフラ設計/` |
14
+ | API 仕様 | `docs/06_API仕様/` |
15
+
16
+ 手順・コマンド・ロックの考え方は **[spec-runner のフロー](spec-runner-フロー.md)** を参照してください(`npx spec-runner` 時にコピーされます)。
17
+
18
+ ---
19
+
20
+ ## プレビュー起動
21
+
22
+ リポジトリルートで次を実行します(Python 3 と `requirements-docs.txt` 用の仮想環境 `.venv-docs/` が使われます)。
23
+
24
+ ```bash
25
+ ./.spec-runner/scripts/docs-serve.sh
26
+ ```
27
+
28
+ `8000` 番が使用中の場合はポートを変えられます。
29
+
30
+ ```bash
31
+ DOCS_PORT=8001 ./.spec-runner/scripts/docs-serve.sh
32
+ ```
@@ -0,0 +1,16 @@
1
+ site_name: プロジェクト設計ドキュメント
2
+ site_description: 憲章・ユースケース・ドメイン・アーキテクチャ等(spec-runner の docs/ 配下を閲覧)
3
+ theme:
4
+ name: material
5
+ language: ja
6
+ features:
7
+ - navigation.sections
8
+ - navigation.expand
9
+ - content.code.copy
10
+ markdown_extensions:
11
+ - admonition
12
+ - toc:
13
+ permalink: true
14
+ # 「ホーム」を先頭に固定し、それ以外の Markdown(01_憲章 … など)は MkDocs が自動でナビに追加
15
+ nav:
16
+ - ホーム: index.md
@@ -0,0 +1,2 @@
1
+ mkdocs==1.6.1
2
+ mkdocs-material==9.7.6