phasegate 0.191.0 → 0.222.0

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 (77) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.ja.md +52 -15
  3. package/README.md +39 -11
  4. package/docs/ADR/030-injection-threat-model-and-trust-root.md +145 -0
  5. package/docs/guide/hooks-integration.md +101 -1
  6. package/docs/guide/installation.md +1 -1
  7. package/docs/guide/quick-vs-full-mode.md +1 -1
  8. package/docs/guide/skills-overview.md +7 -8
  9. package/package.json +1 -1
  10. package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +131 -63
  11. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +31 -4
  12. package/scripts/harness/agent-integration/presentation/spotlight.ts +65 -0
  13. package/scripts/harness/biome-ast-engine/application/mappers/build-harness-error-payload-output-mapper.ts +3 -3
  14. package/scripts/harness/biome-ast-engine/infrastructure/mappers/rule-violation-code-mapper.ts +3 -3
  15. package/scripts/harness/biome-ast-engine/presentation/cli/harness-lint-command-handler.ts +6 -4
  16. package/scripts/harness/ci-governance/application/dto/pin-integrity-input.ts +8 -0
  17. package/scripts/harness/ci-governance/application/dto/pin-integrity-output.ts +9 -0
  18. package/scripts/harness/ci-governance/application/dto/verify-integrity-input.ts +7 -0
  19. package/scripts/harness/ci-governance/application/dto/verify-integrity-output.ts +10 -0
  20. package/scripts/harness/ci-governance/application/usecases/pin-integrity-usecase.ts +60 -0
  21. package/scripts/harness/ci-governance/application/usecases/verify-integrity-usecase.ts +46 -0
  22. package/scripts/harness/ci-governance/composition-root.ts +67 -64
  23. package/scripts/harness/ci-governance/domain/ports/integrity-manifest-repository-port.ts +14 -0
  24. package/scripts/harness/ci-governance/domain/ports/sha256-hasher-port.ts +10 -0
  25. package/scripts/harness/ci-governance/domain/services/integrity-checker.ts +42 -0
  26. package/scripts/harness/ci-governance/domain/value-objects/integrity-drift.ts +16 -0
  27. package/scripts/harness/ci-governance/domain/value-objects/integrity-manifest.ts +49 -0
  28. package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +40 -0
  29. package/scripts/harness/ci-governance/infrastructure/adapters/file-system-sha256-hasher-adapter.ts +17 -0
  30. package/scripts/harness/ci-governance/infrastructure/adapters/harness-api-command-existence-adapter.ts +7 -73
  31. package/scripts/harness/ci-governance/infrastructure/adapters/integrity-manifest-json-repository-adapter.ts +83 -0
  32. package/scripts/harness/ci-governance/presentation/handlers/integrity-handler.ts +76 -0
  33. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +60 -28
  34. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +33 -8
  35. package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +90 -0
  36. package/scripts/harness/harness-error/infrastructure/registry/l1-error-definitions.ts +9 -9
  37. package/scripts/harness/installation/application/bundled-skill-selection.ts +2 -5
  38. package/scripts/harness/installation/application/usecases/run-reconcile.ts +69 -1
  39. package/scripts/harness/main.ts +257 -105
  40. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +65 -3
  41. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +44 -40
  42. package/scripts/harness/setup/skill-deployer.ts +2 -4
  43. package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +82 -49
  44. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +133 -53
  45. package/scripts/harness/validator-system/composition-root.ts +153 -99
  46. package/scripts/harness/validator-system/domain/ports/coverage-attestation-gating-policy-port.ts +14 -0
  47. package/scripts/harness/validator-system/domain/ports/coverage-attestation-verification-policy-port.ts +30 -0
  48. package/scripts/harness/validator-system/domain/ports/injection-scan-policy-port.ts +14 -0
  49. package/scripts/harness/validator-system/domain/services/coverage-attestation-gating-service.ts +56 -0
  50. package/scripts/harness/validator-system/domain/services/coverage-attestation-verification-service.ts +45 -0
  51. package/scripts/harness/validator-system/domain/services/injection-pattern-scan-service.ts +118 -0
  52. package/scripts/harness/validator-system/domain/value-objects/attestation-verification-report.ts +59 -0
  53. package/scripts/harness/validator-system/domain/value-objects/coverage-gating-report.ts +67 -0
  54. package/scripts/harness/validator-system/domain/value-objects/injection-scan-report.ts +55 -0
  55. package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +37 -31
  56. package/scripts/harness/validator-system/infrastructure/adapters/adr-foundation-reference-adapter.ts +13 -7
  57. package/scripts/harness/validator-system/infrastructure/adapters/file-system-coverage-attestation-gating-adapter.ts +87 -0
  58. package/scripts/harness/validator-system/infrastructure/adapters/file-system-coverage-attestation-verification-adapter.ts +165 -0
  59. package/scripts/harness/validator-system/infrastructure/adapters/file-system-injection-scan-adapter.ts +82 -0
  60. package/skills/README.md +1 -1
  61. package/skills/codebase-mapper/SKILL.md +1 -1
  62. package/skills/consistency-checker/references//343/203/201/343/202/247/343/203/203/343/202/257/343/203/252/343/202/271/343/203/210.md +1 -1
  63. package/skills/doc-health-checker/SKILL.md +148 -0
  64. package/skills/release-publisher/SKILL.md +101 -0
  65. package/skills/skill-creator/SKILL.md +74 -332
  66. package/skills/story-implementor/SKILL.md +52 -0
  67. package/skills/story-mapper/SKILL.md +4 -0
  68. package/skills/story-writer/SKILL.md +9 -0
  69. package/skills/uiux-designer/references/uiux-design-template.md +4 -4
  70. package/skills/unit-designer/SKILL.md +3 -1
  71. package/templates/.claude/scripts/deny-check.sh +260 -0
  72. package/skills/doc-freshness-checker/SKILL.md +0 -140
  73. package/skills/implementation-planner/SKILL.md +0 -169
  74. package/skills/implementation-planner/references/document-structure.md +0 -116
  75. package/skills/implementation-planner/references/plan-template.md +0 -177
  76. package/skills/implementation-planner/references/workflow.md +0 -164
  77. package/skills/pointer-validator/SKILL.md +0 -105
@@ -90,11 +90,271 @@ glob_to_regex() {
90
90
  printf '%s' "$1" | sed 's/\*/.*/g'
91
91
  }
92
92
 
93
+ # --- git subcommand allowlist (default-deny) ---------------------------------
94
+ # Enumerated deny lists for git always leak (e.g. `git switch` slipped past the
95
+ # `git checkout*` / `git reset*` deny rules). We therefore invert the policy for
96
+ # git: only the subcommands below are permitted; every other git subcommand is
97
+ # denied by default. To grant a new git subcommand, a human adds it here.
98
+ #
99
+ # Rationale for the set: read-only inspection, staging/commit/tag creation, and
100
+ # worktree/fetch operations that agents legitimately use. History- and
101
+ # working-tree-mutating subcommands (checkout, switch, reset, rebase, merge,
102
+ # cherry-pick, revert, stash, clean, update-ref, reflog, filter-branch,
103
+ # replace, am, ...) are intentionally absent so they fail closed.
104
+ GIT_ALLOWED_SUBCOMMANDS=(
105
+ status log show diff add commit tag restore rev-parse rev-list
106
+ merge-base branch worktree fetch grep cat-file ls-files ls-tree
107
+ ls-remote init remote describe blame shortlog
108
+ for-each-ref name-rev check-ignore check-attr
109
+ stripspace var help version whatchanged push
110
+ )
111
+
112
+ # `symbolic-ref` is deliberately NOT in the allowlist above: its write form
113
+ # (`git symbolic-ref HEAD refs/heads/<branch>` or `git symbolic-ref -d HEAD`)
114
+ # re-points HEAD, i.e. it is a checkout-equivalent HEAD/history mutation that the
115
+ # default-deny policy exists to block. Only the read form (reporting the ref HEAD
116
+ # points at, e.g. `git symbolic-ref HEAD` / `git symbolic-ref --short HEAD`) is
117
+ # state-preserving and therefore permitted. This guard, checked before the plain
118
+ # allowlist, allows the read form and denies every write form.
119
+ check_symbolic_ref() {
120
+ local segment="$1"
121
+ local sub
122
+ sub=$(extract_git_subcommand "$segment")
123
+ [[ "$sub" != "symbolic-ref" ]] && return 0
124
+
125
+ # Re-tokenize and walk to the subcommand, then inspect its arguments.
126
+ local -a tokens
127
+ read -ra tokens <<< "$segment"
128
+ local i=1
129
+ local n=${#tokens[@]}
130
+ # Advance past global options to the `symbolic-ref` token (mirrors
131
+ # extract_git_subcommand's flag handling so flag-stuffing cannot evade this).
132
+ while (( i < n )); do
133
+ case "${tokens[$i]}" in
134
+ -C|-c|--git-dir|--work-tree|--namespace|--exec-path|--config-env)
135
+ i=$(( i + 2 )) ;;
136
+ --git-dir=*|--work-tree=*|--namespace=*|--exec-path=*|--config-env=*)
137
+ i=$(( i + 1 )) ;;
138
+ --no-pager|--paginate|--no-replace-objects|--bare|--literal-pathspecs|--no-optional-locks|--html-path|--man-path|--info-path)
139
+ i=$(( i + 1 )) ;;
140
+ symbolic-ref)
141
+ break ;;
142
+ -*)
143
+ i=$(( i + 1 )) ;;
144
+ *)
145
+ break ;;
146
+ esac
147
+ done
148
+ # Skip the `symbolic-ref` token itself.
149
+ i=$(( i + 1 ))
150
+
151
+ # Count positional (non-flag) arguments after the subcommand. A read is
152
+ # `symbolic-ref [--short|-q] <name>` (<= 1 positional, no delete). A write is
153
+ # `symbolic-ref <name> <ref>` (>= 2 positionals) or `symbolic-ref -d <name>`.
154
+ local positional=0
155
+ while (( i < n )); do
156
+ local arg="${tokens[$i]}"
157
+ case "$arg" in
158
+ -d|--delete)
159
+ debug_log "BLOCKED git symbolic-ref delete form (segment '$segment')"
160
+ echo "Security policy violation: 'git symbolic-ref' delete form is denied (it mutates HEAD; only the read form is permitted). Segment: '$segment'." >&2
161
+ exit 2 ;;
162
+ -m|--reason)
163
+ # `-m <reason>` accompanies a write; the reason value consumes one token.
164
+ i=$(( i + 2 )); continue ;;
165
+ --short|-q|--quiet)
166
+ # Read-only modifiers; do not count as positionals.
167
+ : ;;
168
+ --)
169
+ : ;;
170
+ -*)
171
+ : ;;
172
+ *)
173
+ positional=$(( positional + 1 )) ;;
174
+ esac
175
+ i=$(( i + 1 ))
176
+ done
177
+
178
+ if (( positional >= 2 )); then
179
+ debug_log "BLOCKED git symbolic-ref write form (segment '$segment')"
180
+ echo "Security policy violation: 'git symbolic-ref' write form (re-pointing HEAD) is denied; it is checkout-equivalent HEAD mutation. Only the read form (e.g. 'git symbolic-ref HEAD') is permitted. Segment: '$segment'." >&2
181
+ exit 2
182
+ fi
183
+ # <= 1 positional and no delete: read form. Allowed.
184
+ return 0
185
+ }
186
+
187
+ # `config` is deliberately NOT in the allowlist above: its write form
188
+ # (`git config <key> <value>`, `--unset`, `--add`, `--edit`, ...) can re-point
189
+ # the hook path itself (`git config core.hooksPath <dir>`), which would disable
190
+ # the entire L0 defence layer. Only read forms (`--get*`, `--list`/`-l`, or a
191
+ # single <key> positional with no value) are state-preserving and therefore
192
+ # permitted. Ambiguous invocations fail closed; read forms combined with scope
193
+ # flags (`--global --list`, `--local --get <key>`, ...) are legitimate and pass.
194
+ check_git_config() {
195
+ local segment="$1"
196
+ local sub
197
+ sub=$(extract_git_subcommand "$segment")
198
+ [[ "$sub" != "config" ]] && return 0
199
+
200
+ # Re-tokenize and walk to the subcommand, then inspect its arguments.
201
+ local -a tokens
202
+ read -ra tokens <<< "$segment"
203
+ local i=1
204
+ local n=${#tokens[@]}
205
+ # Advance past global options to the `config` token (mirrors
206
+ # extract_git_subcommand's flag handling so flag-stuffing cannot evade this).
207
+ while (( i < n )); do
208
+ case "${tokens[$i]}" in
209
+ -C|-c|--git-dir|--work-tree|--namespace|--exec-path|--config-env)
210
+ i=$(( i + 2 )) ;;
211
+ --git-dir=*|--work-tree=*|--namespace=*|--exec-path=*|--config-env=*)
212
+ i=$(( i + 1 )) ;;
213
+ --no-pager|--paginate|--no-replace-objects|--bare|--literal-pathspecs|--no-optional-locks|--html-path|--man-path|--info-path)
214
+ i=$(( i + 1 )) ;;
215
+ config)
216
+ break ;;
217
+ -*)
218
+ i=$(( i + 1 )) ;;
219
+ *)
220
+ break ;;
221
+ esac
222
+ done
223
+ # Skip the `config` token itself.
224
+ i=$(( i + 1 ))
225
+
226
+ # Classify the arguments after the subcommand.
227
+ # read flags -> explicitly allowed (`--get`, `--list`, ...)
228
+ # write flags -> explicitly denied (`--unset`, `--add`, `--edit`, ...)
229
+ # positionals -> counted: 1 positional with no write indicator is the
230
+ # `git config <key>` read; >= 2 positionals is the
231
+ # `git config <key> <value>` write (fail closed).
232
+ # Scope flags (`--global`, `--system`, `--local`, `--worktree`) and other
233
+ # modifiers are neutral: the verdict is driven by read/write flags and the
234
+ # positional count, so `--global --list` passes and `--global k v` fails.
235
+ local read_flag=0
236
+ local positional=0
237
+ while (( i < n )); do
238
+ local arg="${tokens[$i]}"
239
+ case "$arg" in
240
+ --unset|--unset-all|--add|--replace-all|--edit|-e|--remove-section|--rename-section|--set*)
241
+ debug_log "BLOCKED git config write flag '$arg' (segment '$segment')"
242
+ echo "Security policy violation: 'git config' write form ('$arg') is denied; config writes can re-point hooks (core.hooksPath) and disable the L0 defence layer. Only read forms (--get/--get-all/--get-regexp/--list/-l or a bare <key>) are permitted. Segment: '$segment'." >&2
243
+ exit 2 ;;
244
+ --get|--get-all|--get-regexp|--get-urlmatch|--get-color|--get-colorbool|--list|-l)
245
+ read_flag=1 ;;
246
+ --file|-f|--blob|--default|--type)
247
+ # Neutral flags that consume a separate value token.
248
+ i=$(( i + 2 )); continue ;;
249
+ --file=*|--blob=*|--default=*|--type=*)
250
+ : ;;
251
+ --)
252
+ : ;;
253
+ -*)
254
+ # Scope flags and other modifiers: neutral, do not count.
255
+ : ;;
256
+ *)
257
+ # New-style verb subcommands (git >= 2.46) that mutate config.
258
+ if (( positional == 0 )); then
259
+ case "$arg" in
260
+ set|unset|edit|rename-section|remove-section)
261
+ debug_log "BLOCKED git config verb '$arg' (segment '$segment')"
262
+ echo "Security policy violation: 'git config $arg' is a config write form and is denied; config writes can re-point hooks (core.hooksPath) and disable the L0 defence layer. Segment: '$segment'." >&2
263
+ exit 2 ;;
264
+ esac
265
+ fi
266
+ positional=$(( positional + 1 )) ;;
267
+ esac
268
+ i=$(( i + 1 ))
269
+ done
270
+
271
+ # Explicit read flag: allowed regardless of positional count
272
+ # (`--get <key>`, `--get-regexp <pattern>`, `--get-urlmatch <key> <url>`).
273
+ (( read_flag == 1 )) && return 0
274
+
275
+ if (( positional >= 2 )); then
276
+ debug_log "BLOCKED git config write form (segment '$segment')"
277
+ echo "Security policy violation: 'git config' write form (<key> <value>) is denied; config writes can re-point hooks (core.hooksPath) and disable the L0 defence layer. Only read forms (--get/--get-all/--get-regexp/--list/-l or a bare <key>) are permitted. Segment: '$segment'." >&2
278
+ exit 2
279
+ fi
280
+ # <= 1 positional and no write indicator: value read (`git config <key>`)
281
+ # or a no-op. Allowed.
282
+ return 0
283
+ }
284
+
285
+ # Extract the git subcommand from a segment, skipping the `git` binary and any
286
+ # global options that may precede the subcommand:
287
+ # git -C <path> <sub> git --no-pager <sub>
288
+ # git -c key=val <sub> git --git-dir=<dir> <sub>
289
+ # git --work-tree <dir> <sub>
290
+ # Prints the subcommand (or empty string if none / not a git command).
291
+ extract_git_subcommand() {
292
+ # Tokenize on whitespace.
293
+ local -a tokens
294
+ read -ra tokens <<< "$1"
295
+ [[ "${tokens[0]}" != "git" ]] && return 0
296
+ local i=1
297
+ local n=${#tokens[@]}
298
+ while (( i < n )); do
299
+ local tok="${tokens[$i]}"
300
+ case "$tok" in
301
+ # Global flags that take a separate argument.
302
+ -C|-c|--git-dir|--work-tree|--namespace|--exec-path|--config-env)
303
+ i=$(( i + 2 ))
304
+ ;;
305
+ # Global flags bundled with their value (=), or standalone toggles.
306
+ --git-dir=*|--work-tree=*|--namespace=*|--exec-path=*|--config-env=*)
307
+ i=$(( i + 1 ))
308
+ ;;
309
+ --no-pager|--paginate|--no-replace-objects|--bare|--literal-pathspecs|--no-optional-locks|--html-path|--man-path|--info-path)
310
+ i=$(( i + 1 ))
311
+ ;;
312
+ -*)
313
+ # Unknown global flag; skip conservatively.
314
+ i=$(( i + 1 ))
315
+ ;;
316
+ *)
317
+ printf '%s' "$tok"
318
+ return 0
319
+ ;;
320
+ esac
321
+ done
322
+ return 0
323
+ }
324
+
325
+ check_git_allowlist() {
326
+ local segment="$1"
327
+ local sub
328
+ sub=$(extract_git_subcommand "$segment")
329
+ # Not a git command, or `git` with no subcommand (e.g. `git`, `git --help`).
330
+ [[ -z "$sub" ]] && return 0
331
+ # `symbolic-ref` is adjudicated by check_symbolic_ref (read form allowed,
332
+ # write form denied); do not treat its absence from the allowlist as a deny.
333
+ [[ "$sub" == "symbolic-ref" ]] && return 0
334
+ # `config` is adjudicated by check_git_config (read forms allowed, write
335
+ # forms denied); do not treat its absence from the allowlist as a deny.
336
+ [[ "$sub" == "config" ]] && return 0
337
+ local allowed
338
+ for allowed in "${GIT_ALLOWED_SUBCOMMANDS[@]}"; do
339
+ [[ "$sub" == "$allowed" ]] && return 0
340
+ done
341
+ debug_log "BLOCKED git subcommand '$sub' not in allowlist (segment '$segment')"
342
+ echo "Security policy violation: git subcommand '$sub' is not in the agent allowlist (default-deny for git). Segment: '$segment'. If this subcommand is genuinely needed, a human must add it to GIT_ALLOWED_SUBCOMMANDS in .claude/scripts/deny-check.sh." >&2
343
+ exit 2
344
+ }
345
+
93
346
  check_segment() {
94
347
  local segment="$1"
95
348
  # Strip leading whitespace so "^pattern" anchors match after operators.
96
349
  segment="${segment#"${segment%%[![:space:]]*}"}"
97
350
  [[ -z "$segment" ]] && return 0
351
+ # git subcommands are default-deny (allowlist); check that first.
352
+ # symbolic-ref and config get a dedicated read-vs-write adjudication before
353
+ # the plain allowlist (their write forms mutate HEAD / the hook path and
354
+ # must fail closed).
355
+ check_symbolic_ref "$segment"
356
+ check_git_config "$segment"
357
+ check_git_allowlist "$segment"
98
358
  for pattern in "${DENY_PATTERNS[@]}"; do
99
359
  local regex_pattern
100
360
  regex_pattern=$(glob_to_regex "$pattern")
@@ -1,140 +0,0 @@
1
- ---
2
- name: doc-freshness-checker
3
- description: 設計文書の鮮度チェック(L4バリデータ拡張)。`phasegate check-freshness` CLIを使い、設計文書の最終更新日が閾値を超えていないか、コード変更と設計文書の乖離がないかを検出する。使用タイミング: 「設計文書が古くなっていないか確認して」「ドキュメントの鮮度チェックを実行して」「L4 freshness チェック」「設計とコードの乖離を調べて」など。
4
- model: sonnet
5
- review: opus
6
- languages: [typescript]
7
- ---
8
-
9
- # Doc Freshness Checker
10
-
11
- ## 目的
12
-
13
- 設計文書の鮮度(freshness)を検証し、古くなった文書や対応コードとの乖離を検出するスキル。
14
- `phasegate check-freshness` CLIをラップし、結果を解釈・対処する。
15
-
16
- ## 前提条件
17
-
18
- - `phasegate.config.json` に `docFreshnessThresholds` が設定されていること(未設定時はデフォルト値使用)
19
- - git リポジトリ内で実行すること(最終更新日は `git log` で判定)
20
-
21
- ## 入力
22
-
23
- - 対象ディレクトリ: `--dir <path>` または `phasegate.config.json` の `constructionDir`(デフォルト `docs/`)
24
- - 閾値: `--threshold <days>` または `docFreshnessThresholds`(未設定時はデフォルト30日)
25
- - git 履歴(最終更新日の判定に使用)
26
-
27
- ---
28
-
29
- ## ⚠️ 2フェーズ実行ルール
30
-
31
- - **Phase 1(計画)**: チェック対象スコープを確認し、人間の承認を得る
32
- - **Phase 2(実行)**: CLIを実行し、結果を解釈してアクションを提案する
33
-
34
- **Phase 1/2を同時に実行してはならない。**
35
-
36
- ---
37
-
38
- ## Phase 1: チェック計画(plan)
39
-
40
- ### 出力(会話内のみ)
41
-
42
- ```markdown
43
- # Doc Freshness チェック計画
44
-
45
- ## チェック対象スコープ
46
- - ディレクトリ: {phasegate.config.json の constructionDir、デフォルト: docs/}
47
- - 閾値: {phasegate.config.json の値 or デフォルト 30日}
48
-
49
- ## 実行コマンド
50
- npx phasegate check-freshness [--dir {path}] [--threshold {days}]
51
-
52
- ## QA
53
- [Question] Q1: ...
54
- [Answer]
55
- ```
56
-
57
- ### Phase 1 完了条件
58
- - スコープを報告した
59
- - 人間にボールを渡した
60
- - **CLIはまだ実行していない**
61
-
62
- ---
63
-
64
- ## Phase 2: 実行(execution)
65
-
66
- ### Step 1: CLIの実行
67
-
68
- ```bash
69
- npx phasegate check-freshness
70
- ```
71
-
72
- オプション:
73
- - `--dir <path>` — チェック対象ディレクトリ(デフォルト: `phasegate.config.json` の `constructionDir`)
74
- - `--threshold <days>` — 警告閾値(日数)
75
-
76
- ### Step 2: 結果の解釈
77
-
78
- `CheckDocFreshnessOutput` の構造:
79
-
80
- | フィールド | 意味 |
81
- |-----------|------|
82
- | `results[].status` | `ok` / `warn` / `error` |
83
- | `results[].documentPath` | チェック対象ファイルパス |
84
- | `results[].daysSinceUpdate` | 最終更新からの日数 |
85
- | `results[].threshold` | 設定閾値 |
86
- | `summary.error` | エラー件数(即対応必要) |
87
- | `summary.warn` | 警告件数(確認推奨) |
88
-
89
- ### Step 3: アクションの提案
90
-
91
- | 状態 | 推奨アクション |
92
- |------|--------------|
93
- | `error`(閾値超過) | cascade-updater で上位設計文書を更新 |
94
- | `warn`(閾値近接) | 設計文書の内容確認・必要に応じて更新 |
95
- | `ok` | 対応不要 |
96
-
97
- ### 出力フォーマット
98
-
99
- ```markdown
100
- # Doc Freshness チェック結果
101
-
102
- ## サマリー
103
- - 総ドキュメント数: N
104
- - ok: N / warn: N / error: N
105
-
106
- ## 要対応(error)
107
- | ファイル | 最終更新 | 閾値超過日数 | 推奨アクション |
108
- |---------|---------|------------|--------------|
109
-
110
- ## 要確認(warn)
111
- | ファイル | 最終更新 | 残り日数 |
112
- |---------|---------|---------|
113
-
114
- ## 次のアクション
115
- (errorがある場合は `cascade-updater` の実行を提案)
116
- ```
117
-
118
- ---
119
-
120
- ## phasegate.config.json 設定例
121
-
122
- ```json
123
- {
124
- "docFreshnessThresholds": {
125
- "domain_model.md": 90,
126
- "logical_design.md": 60,
127
- "unit_test_design.md": 30,
128
- "default": 30
129
- }
130
- }
131
- ```
132
-
133
- ---
134
-
135
- ## 関連スキル
136
-
137
- | スキル | 用途 |
138
- |-------|------|
139
- | `cascade-updater` | errorが検出された設計文書の更新 |
140
- | `consistency-checker` | 文書間整合性の検証(freshness修正後の確認) |
@@ -1,169 +0,0 @@
1
- ---
2
- name: implementation-planner
3
- description: "Unit仕様とドメインモデル設計を元に実装計画を立てる。WI IDや機能名から関連Unitを特定し、API設計・レイヤー別実装方針を整理してmdファイルで出力する。使用タイミング: 実装計画を立てて、WI-XXXの実装方針を決めて、この機能の設計を整理して、など実装前の計画策定時。"
4
- model: sonnet
5
- review: opus
6
- languages: [typescript]
7
- ---
8
-
9
- # Implementation Planner
10
-
11
- ## 目的
12
-
13
- UnitドキュメントとConstructionのドメインモデル設計を元に、**設計フェーズの実装計画**を体系的に立案する。
14
-
15
- ## ⚠️ `story-implementor` との役割分担
16
-
17
- | 観点 | `implementation-planner`(本スキル) | `story-implementor` |
18
- |------|-------------------------------------|---------------------|
19
- | **目的** | 設計段階で実装方針を整理・合意する | TDD実装を実行する |
20
- | **タイミング** | 論理設計の前後(設計の方向性確認) | テスト設計・カバレッジ検証の後 |
21
- | **出力** | 実装計画書(API設計・レイヤー別方針) | TDD実装計画 → 実装コード |
22
- | **テスト設計** | 参照しない(設計フェーズのため) | 必須(テスト設計完了が前提) |
23
-
24
- **使い分けの指針:**
25
- - 「この機能どう実装する?」→ `implementation-planner`
26
- - 「テスト設計も終わった、TDD実装を始めたい」→ `story-implementor`
27
-
28
- ## ⚠️ 3フェーズ実行ルール
29
-
30
- **このスキルは3フェーズで実行する。**
31
- - **Phase 1(計画)**: Opus がスコープ・方針・不明点を整理し、人間の承認を得る
32
- - **Phase 2(実行)**: 委任先モデルに委任して成果物を生成する(`npx phasegate delegate-sonnet` 経由)
33
- - **Phase 3(レビュー)**: Opus が成果物を検証し、問題があれば直接修正する
34
-
35
- **Phase 1/2/3を同時に実行してはならない。モデルルーティングの詳細は `docs/principles/model-routing.md` を参照(consumer プロジェクトでは `node_modules/phasegate/docs/principles/model-routing.md`、phasegate 自リポジトリでは `docs/principles/model-routing.md` を参照する)。**
36
-
37
- ---
38
-
39
- ## ワークフロー
40
-
41
- ## 前提条件チェック(Pre-flight, BLOCKING)
42
-
43
- Before generating any plan, verify `docs/inception/{unit}/WI-XXX/description.md` exists.
44
- If not, halt and ask the user to create the WI first, or offer to run `phasegate scaffold-wi <unit> <story|issue|chore>`.
45
-
46
- ```
47
- 入力解析 → Unit特定 → ドメインモデル確認 → 既存実装確認 → 計画作成 → 出力
48
- ```
49
-
50
- ### Step 1: 入力解析
51
-
52
- ユーザー入力から抽出:
53
- - WI ID(WI-XXX形式)
54
- - 機能名・タスク説明
55
- - 優先度・制約条件
56
-
57
- ### Step 2: Unit特定
58
-
59
- 1. `docs/product/units/integration_contract.md`を読み込み
60
- 2. 関連する公開APIエンドポイントを特定
61
- 3. 該当Unitの`{unit}.md`を確認
62
- 4. Unit間依存関係を整理
63
-
64
- **検索方法:**
65
- - Grep/Globツールを使用して `docs/product/units/` 配下からストーリーIDやキーワードを検索する
66
- - `integration_contract.md` から関連する公開APIエンドポイントを特定する
67
-
68
- ### Step 3: ドメインモデル確認
69
-
70
- 1. `docs/product/construction/{context}/domain_model.md`を読み込み
71
- 2. 以下を把握:
72
- - 集約と不変条件
73
- - エンティティ・値オブジェクト
74
- - ドメインイベント
75
- - 状態遷移
76
- 3. 必要に応じて`shared_kernel/domain_model.md`を参照
77
-
78
- ### Step 4: 既存実装確認
79
-
80
- - Glob/Readツールを使用してプロジェクトの実装ディレクトリ構造を確認する
81
- - 既存の実装パターンを検索し、コードスタイル・ファイル配置を把握する
82
-
83
- ### Step 5: 計画作成
84
-
85
- [references/plan-template.md](references/plan-template.md)のフォーマットに従って:
86
- 1. API設計(新規/既存拡張)
87
- 2. レイヤー別実装内容
88
- 3. 実装ステップ分解
89
- 4. 影響範囲特定
90
-
91
- ## 出力ファイル
92
-
93
- ### Step 6: 出力
94
-
95
- 計画をmdファイルとして出力。パスの推奨:
96
- ```
97
- docs/inception/{task_id}_plan.md
98
- docs/inception/{unit}/WI-XXX/tdd_implementation_plan.md
99
- ```
100
-
101
- > **パス注記**: 本スキルが扱う設計文書パス(`docs/inception/...` / `docs/product/units/...` / `docs/product/construction/...`)は既定値であり、consumer が `phasegate.config.json` の `paths` 設定で上書きしている場合はそちらが優先される。
102
-
103
- **[Question][Answer]セクション必須**: 不明点や確認事項をまとめ、ユーザーからのフィードバックを受け取れるようにする。
104
-
105
- ---
106
-
107
- ## 入力(参照ドキュメント)
108
-
109
- | ファイル | 用途 |
110
- |----------|------|
111
- | `docs/product/units/integration_contract.md` | Unit間API定義・依存関係 |
112
- | `docs/product/units/{unit}.md` | ユーザーストーリー・機能要件 |
113
- | `docs/product/construction/{context}/domain_model.md` | ドメインモデル設計 |
114
-
115
- **詳細は以下を参照:**
116
- - [document-structure.md](references/document-structure.md): ドキュメント構造リファレンス
117
- - [workflow.md](references/workflow.md): 詳細ワークフロー
118
- - [plan-template.md](references/plan-template.md): 出力テンプレート
119
-
120
- ---
121
-
122
- ## Unit一覧(クイックリファレンス)
123
-
124
- 実行時に `docs/product/units/` 配下のUnit定義ファイルを動的に読み取ること。ハードコードしない。
125
-
126
- ---
127
-
128
- ### Phase 2 最低出力基準(Sonnet委任時の品質制約)
129
-
130
- 以下の基準を満たさない出力は不完全とみなし、Phase 3レビューでBLOCKとする。
131
-
132
- | 基準 | 最低要件 |
133
- |------|---------|
134
- | Unit特定 | 対象ストーリー/機能に関連するUnitが正しく特定されていること |
135
- | ドメインモデル参照 | 関連する集約・エンティティ・値オブジェクトが列挙されていること |
136
- | API設計 | 新規/既存拡張のエンドポイントが具体的に定義されていること |
137
- | レイヤー別実装内容 | 各層(Domain/UseCase/Controller/Infrastructure)の実装内容が記載されていること |
138
- | 実装ステップ | 実装順序が具体的なステップに分解されていること |
139
- | 影響範囲 | 変更が他Unit・他コンポーネントに与える影響が分析されていること |
140
- | QAセクション | 不明点・確認事項が[Question][Answer]形式で記載されていること |
141
-
142
- ---
143
-
144
- ## Phase 3: レビュー(Opus review)
145
-
146
- ### 実行主体
147
- メインセッション(model-routing.md の Architect ロール)が実行する。Sonnetへの再委任は行わない。
148
-
149
- ### レビュー手順
150
- 1. Sonnetが出力したファイルを読み込む
151
- 2. `docs/principles/model-routing.md` の「レビュー観点」節に沿って検証する
152
- 3. **スキル固有レビュー観点**を検証する
153
- 4. 判定結果を出力する
154
-
155
- ### スキル固有レビュー観点(BLOCK基準)
156
- - [ ] 対象Unit/ドメインモデルの特定が正確か
157
- - [ ] API設計が統合契約と整合しているか
158
- - [ ] レイヤー間の依存方向が正しいか(Domain → Port → UseCase → Controller)
159
- - [ ] 実装ステップの順序が論理的か(依存関係に沿っているか)
160
- - [ ] 影響範囲の分析が漏れなく行われているか
161
-
162
- ### 判定と修正
163
- - **BLOCK項目にFAIL** → Opusが直接修正してから完了とする
164
- - **WARNのみFAIL** → Opusが直接修正してから完了とする
165
- - **全PASS** → 完了
166
-
167
- ## コードベース構成(クイックリファレンス)
168
-
169
- 実行時にプロジェクトのディレクトリ構造を動的に確認すること。ハードコードしない。