phasegate 0.44.0 → 0.63.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.
- package/README.ja.md +32 -0
- package/README.md +33 -0
- package/docs/guide/codex-integration.md +162 -0
- package/docs/guide/quick-vs-full-mode.md +141 -0
- package/package.json +1 -1
- package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +60 -0
- package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +299 -0
- package/scripts/harness/agent-integration/presentation/session-start-hook.ts +54 -0
- package/scripts/harness/agent-integration/presentation/user-prompt-submit-hook.ts +70 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +15 -0
- package/scripts/harness/integrations/pre-commit.ts +128 -28
- package/scripts/harness/main.ts +87 -9
- package/scripts/harness/phase2-extensions/application/dto/check-initial-creation-expiration-input.ts +9 -0
- package/scripts/harness/phase2-extensions/application/dto/check-initial-creation-expiration-output.ts +17 -0
- package/scripts/harness/phase2-extensions/application/usecases/check-initial-creation-expiration-usecase.ts +103 -0
- package/scripts/harness/phase2-extensions/composition-root.ts +22 -0
- package/scripts/harness/phase2-extensions/domain/aggregates/initial-creation-expiration-rule.ts +103 -0
- package/scripts/harness/phase2-extensions/domain/ports/frontmatter-reader-port.ts +17 -0
- package/scripts/harness/phase2-extensions/domain/ports/initial-creation-age-port.ts +9 -0
- package/scripts/harness/phase2-extensions/domain/ports/initial-creation-expiration-config-port.ts +9 -0
- package/scripts/harness/phase2-extensions/domain/services/initial-creation-expiration-check-service.ts +54 -0
- package/scripts/harness/phase2-extensions/domain/value-objects/initial-creation-age.ts +54 -0
- package/scripts/harness/phase2-extensions/infrastructure/adapters/git-log-initial-creation-age-adapter.ts +77 -0
- package/scripts/harness/phase2-extensions/infrastructure/adapters/harness-config-initial-creation-expiration-adapter.ts +57 -0
- package/scripts/harness/phase2-extensions/infrastructure/adapters/markdown-frontmatter-reader-adapter.ts +56 -0
- package/scripts/harness/phase2-extensions/presentation/formatters/initial-creation-expiration-result-formatter.ts +23 -0
- package/scripts/harness/phase2-extensions/presentation/handlers/check-initial-creation-expiration-handler.ts +38 -0
- package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +20 -0
- package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +83 -0
- package/scripts/harness/quick-mode/composition-root.ts +12 -0
- package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +38 -32
- package/scripts/harness/quick-mode/domain/value-objects/quick-mode-config.ts +36 -4
- package/scripts/harness/quick-mode/infrastructure/adapters/harness-config-quick-mode-config-adapter.ts +6 -0
- package/scripts/harness/quick-mode/presentation/formatters/change-category-formatter.ts +42 -0
- package/scripts/harness/quick-mode/presentation/handlers/check-change-category-handler.ts +50 -0
- package/scripts/harness/setup/skill-deployer.ts +30 -0
- package/scripts/harness/traceability-model/composition-root.ts +14 -0
- package/scripts/harness/traceability-model/domain/value-objects/project-relative-path.ts +3 -0
- package/scripts/harness/traceability-model/infrastructure/parsers/markdown-story-annotation-parser.ts +39 -4
- package/scripts/harness/traceability-model/presentation/cli/validate-metadata-command-handler.ts +103 -9
- package/skills/domain-designer/SKILL.md +34 -0
- package/skills/it-test-logic-designer/SKILL.md +16 -0
- package/skills/logical-designer/SKILL.md +34 -0
- package/skills/quick-implementor/SKILL.md +10 -1
- package/skills/scenario-test-logic-designer/SKILL.md +16 -0
- package/skills/story-implementor/SKILL.md +58 -0
- package/skills/unit-designer/SKILL.md +41 -0
- package/skills/unit-test-logic-designer/SKILL.md +18 -0
- package/templates/.codex/hooks.json +63 -0
- package/templates/logical_design.template.md +79 -0
- package/templates/source.template.ts +18 -0
- package/templates/test.template.ts +37 -0
package/README.ja.md
CHANGED
|
@@ -16,6 +16,7 @@ AIエージェント(Claude Code, Codex, Cursor, Copilot 等)が生成する
|
|
|
16
16
|
- [AIDLC スキル](#aidlc-スキル)
|
|
17
17
|
- [メタデータ規約](#メタデータ規約)
|
|
18
18
|
- [Claude Code Hooks](#claude-code-hooks)
|
|
19
|
+
- [Codex CLI Integration](#codex-cli-integration)
|
|
19
20
|
- [カスタムフェーズゲート](#カスタムフェーズゲート)
|
|
20
21
|
- [CI/CD テンプレート](#cicd-テンプレート)
|
|
21
22
|
- [導入後のプロジェクト構造](#導入後のプロジェクト構造)
|
|
@@ -32,6 +33,7 @@ Phasegate は **「設計なしの実装を物理的に拒否する」** ツー
|
|
|
32
33
|
| **5層バリデーション** | L1(AST) → L2(Pre-commit) → L3(CI) → L4(週次) の段階的品質チェック |
|
|
33
34
|
| **28 AIDLC スキル** | 要求定義 → 設計 → テスト設計 → TDD実装の全フェーズをスキルとして提供 |
|
|
34
35
|
| **Claude Code Hooks** | Write/Edit 時に自動でゲートチェック・Biome lint を実行 |
|
|
36
|
+
| **Codex CLI Hooks** | Bash 書き込み時にフェーズゲート / 保護ファイル / Biome lint を実行(ネイティブ `apply_patch` は pre-commit でカバー) |
|
|
35
37
|
| **Quick Mode** | バグ修正・ドキュメント修正など軽微な変更ではゲートを緩和して高速実行 |
|
|
36
38
|
|
|
37
39
|
---
|
|
@@ -576,6 +578,36 @@ export class ConfigSchema { ... }
|
|
|
576
578
|
|
|
577
579
|
---
|
|
578
580
|
|
|
581
|
+
## Codex CLI Integration
|
|
582
|
+
|
|
583
|
+
Phasegate は [OpenAI Codex CLI](https://developers.openai.com/codex/cli) でも同じ防御機構を提供します。CLI (`npx phasegate hook <event>`) 自体は agent-agnostic なため、Claude Code と Codex で同じコマンドが使えます。
|
|
584
|
+
|
|
585
|
+
### セットアップ(2 ステップ)
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
# 1. Codex 向けに初期化(.codex/hooks.json を自動配置)
|
|
589
|
+
npx phasegate init --name my-project --agent codex --with-husky
|
|
590
|
+
|
|
591
|
+
# 2. Codex hooks フィーチャーフラグを有効化
|
|
592
|
+
codex features enable codex_hooks
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Claude + Codex 両対応プロジェクトは `--agent both` を指定してください。
|
|
596
|
+
|
|
597
|
+
### カバレッジと既知の制約
|
|
598
|
+
|
|
599
|
+
Codex のネイティブ `apply_patch` ツールは内部の `ApplyPatchHandler` 経由で実行され hook を発火しません([openai/codex#16732](https://github.com/openai/codex/issues/16732))。このため pre-edit hard block は Bash 経由の書き込みに限定され、ネイティブ `apply_patch` の違反は **pre-commit (L2)** で commit 時にブロックされます。
|
|
600
|
+
|
|
601
|
+
| 編集経路 | 事前 hard block | commit 時 block |
|
|
602
|
+
|---|---|---|
|
|
603
|
+
| Bash 書き込み(`sed -i`, `tee`, heredoc, `cat >`) | ✅ `PreToolUse(Bash)` | ✅ pre-commit |
|
|
604
|
+
| Bash 経由 `apply_patch <<'PATCH'` | ✅ `PreToolUse(Bash)`(`BashWriteTargetExtractor` で heredoc 解析) | ✅ pre-commit |
|
|
605
|
+
| Codex ネイティブ `apply_patch` ツール | ❌ Codex 側の制約で hook 非発火 | ✅ pre-commit |
|
|
606
|
+
|
|
607
|
+
**推奨運用**: こまめに commit することで、ネイティブ `apply_patch` 経由の違反を早期に surface できます。詳細は [docs/guide/codex-integration.md](docs/guide/codex-integration.md) を参照してください。
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
579
611
|
## カスタムフェーズゲート
|
|
580
612
|
|
|
581
613
|
デフォルトでは AIDLC フェーズ依存モデルが適用されますが、`gates[]` 配列で独自のゲートを定義できます。
|
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ Works with **Claude Code, Codex, Cursor, Copilot**, or any other AI agent.
|
|
|
26
26
|
| **Phase Dependency Model** | Blocks implementation when required design documents are missing |
|
|
27
27
|
| **Quick Mode** | Lightweight gate for bugfixes, docs, tests, and config changes |
|
|
28
28
|
| **Claude Code Hooks** | Native PreToolUse / PostToolUse / Stop hook integration |
|
|
29
|
+
| **Codex CLI Hooks** | `PreToolUse(Bash)` / `PostToolUse(Bash)` / `Stop` hook integration (native `apply_patch` falls back to pre-commit) |
|
|
29
30
|
| **HarnessError Format** | Every error includes ADR references and fix examples for AI self-correction |
|
|
30
31
|
| **Configurable Phase Gates** | Define custom gates with `gates[]` in config. Default uses AIDLC phase dependencies |
|
|
31
32
|
| **Protected File Control** | Configure which files are protected from AI writes via `protectedFiles.exclude` |
|
|
@@ -253,6 +254,36 @@ All hook errors use the `HarnessError` format with ADR references and fix exampl
|
|
|
253
254
|
|
|
254
255
|
---
|
|
255
256
|
|
|
257
|
+
## Codex CLI Integration
|
|
258
|
+
|
|
259
|
+
Phasegate also integrates with [OpenAI Codex CLI](https://developers.openai.com/codex/cli) via hooks in `.codex/hooks.json`. The CLI itself is agent-agnostic, so the same `npx phasegate hook <event>` commands power both Claude Code and Codex.
|
|
260
|
+
|
|
261
|
+
### Quick setup
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# 1. Initialize with Codex agent support (auto-deploys .codex/hooks.json)
|
|
265
|
+
npx phasegate init --name my-project --agent codex --with-husky
|
|
266
|
+
|
|
267
|
+
# 2. Enable Codex hooks feature flag
|
|
268
|
+
codex features enable codex_hooks
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
For dual-agent projects (Claude + Codex), use `--agent both`.
|
|
272
|
+
|
|
273
|
+
### Coverage and known limitation
|
|
274
|
+
|
|
275
|
+
Because Codex's native `apply_patch` tool is routed through an internal `ApplyPatchHandler` and does not emit hook events ([openai/codex#16732](https://github.com/openai/codex/issues/16732)), pre-edit hard-block coverage is limited to Bash-based writes. Native `apply_patch` violations are caught at commit time by the pre-commit layer.
|
|
276
|
+
|
|
277
|
+
| Path | Pre-edit hard block | Commit-time block |
|
|
278
|
+
|---|---|---|
|
|
279
|
+
| Shell writes (`sed -i`, `tee`, heredoc, `cat >`) | ✅ `PreToolUse(Bash)` | ✅ pre-commit |
|
|
280
|
+
| Bash-invoked `apply_patch <<'PATCH'` | ✅ `PreToolUse(Bash)` (via `BashWriteTargetExtractor`) | ✅ pre-commit |
|
|
281
|
+
| Native `apply_patch` tool call | ❌ not intercepted by Codex today | ✅ pre-commit |
|
|
282
|
+
|
|
283
|
+
**Recommended mitigation**: commit frequently (e.g., after each logical change) so native `apply_patch` violations surface quickly. See the full guide for details.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
256
287
|
## CLI Reference
|
|
257
288
|
|
|
258
289
|
```bash
|
|
@@ -287,6 +318,8 @@ Detailed guides are available under `docs/guide/`:
|
|
|
287
318
|
- [Skills Overview](docs/guide/skills-overview.md) -- 28 skills with AIDLC execution order
|
|
288
319
|
- [5-Layer Defense Model](docs/guide/layer-model.md) -- L0-L4 layer details and HarnessError format
|
|
289
320
|
- [Hooks Integration](docs/guide/hooks-integration.md) -- Claude Code Hooks setup and behavior
|
|
321
|
+
- [Codex Integration](docs/guide/codex-integration.md) -- Codex CLI setup, coverage matrix, and native `apply_patch` limitation
|
|
322
|
+
- [Quick Mode vs Full Mode](docs/guide/quick-vs-full-mode.md) -- When to use `/story-implementor` vs `/quick-implementor`, with decision flow and case studies
|
|
290
323
|
|
|
291
324
|
Additional resources:
|
|
292
325
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Codex CLI Integration
|
|
2
|
+
|
|
3
|
+
Phasegate supports [OpenAI Codex CLI](https://developers.openai.com/codex/cli) through its hooks system, providing quality enforcement similar to the Claude Code experience. Because Codex's hook coverage differs from Claude's, defense is layered across hook-time and commit-time mechanisms.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### Quick setup (recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Initialize with Codex agent support
|
|
11
|
+
npx phasegate init --name my-project --agent codex --with-husky
|
|
12
|
+
|
|
13
|
+
# 2. Enable Codex hooks feature flag
|
|
14
|
+
codex features enable codex_hooks
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For dual-agent projects (Claude + Codex), use `--agent both`.
|
|
18
|
+
|
|
19
|
+
### Manual setup
|
|
20
|
+
|
|
21
|
+
Alternatively, set up Codex integration manually:
|
|
22
|
+
|
|
23
|
+
#### 1. Enable hooks in Codex config
|
|
24
|
+
|
|
25
|
+
Add to `~/.codex/config.toml` (or project `.codex/config.toml`):
|
|
26
|
+
|
|
27
|
+
```toml
|
|
28
|
+
[features]
|
|
29
|
+
codex_hooks = true
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### 2. Install Phasegate hooks
|
|
33
|
+
|
|
34
|
+
Copy the template into your project:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
mkdir -p .codex
|
|
38
|
+
cp node_modules/phasegate/templates/.codex/hooks.json .codex/hooks.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or merge the following into your existing `.codex/hooks.json`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"hooks": {
|
|
46
|
+
"PreToolUse": [
|
|
47
|
+
{
|
|
48
|
+
"matcher": "Bash",
|
|
49
|
+
"hooks": [
|
|
50
|
+
{
|
|
51
|
+
"type": "command",
|
|
52
|
+
"command": "npx phasegate hook pre-tool-use",
|
|
53
|
+
"statusMessage": "phasegate: pre-tool-use check"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"PostToolUse": [
|
|
59
|
+
{
|
|
60
|
+
"matcher": "Bash",
|
|
61
|
+
"hooks": [
|
|
62
|
+
{
|
|
63
|
+
"type": "command",
|
|
64
|
+
"command": "npx phasegate hook post-tool-use",
|
|
65
|
+
"statusMessage": "phasegate: post-tool-use lint"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"Stop": [
|
|
71
|
+
{
|
|
72
|
+
"hooks": [
|
|
73
|
+
{
|
|
74
|
+
"type": "command",
|
|
75
|
+
"command": "npx phasegate hook stop",
|
|
76
|
+
"statusMessage": "phasegate: completion check",
|
|
77
|
+
"timeout": 30
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### 3. Enable the pre-commit hook (critical for Codex)
|
|
87
|
+
|
|
88
|
+
Because Codex's native `apply_patch` tool does not trigger hooks (see [Codex's limitation](#known-limitations)), the pre-commit layer is the primary defense for apply_patch-based edits. Install via husky:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx phasegate init --with-husky # or rerun init with this flag
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Defense Layers in Codex
|
|
95
|
+
|
|
96
|
+
Compared to Claude Code, the enforcement timing is shifted for `apply_patch`-based edits. Coverage is equivalent overall but arrives at different stages.
|
|
97
|
+
|
|
98
|
+
| Concern | Claude Code | Codex |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| Bash-based file writes (`sed -i`, `tee`, heredoc) | `PreToolUse(Bash)` — hard block | `PreToolUse(Bash)` — hard block (same) |
|
|
101
|
+
| Bash-invoked `apply_patch <<'PATCH'` | `PreToolUse(Bash)` — hard block | `PreToolUse(Bash)` — hard block (via Wave 1 `apply_patch` heredoc detection) |
|
|
102
|
+
| **Native `apply_patch` tool calls** | `PreToolUse(Write\|Edit)` — hard block | ⚠️ **Not intercepted by hooks** — deferred to pre-commit |
|
|
103
|
+
| Protected file writes | hook — immediate block | hook (Bash path) + pre-commit (commit path) |
|
|
104
|
+
| Phase-gate enforcement | hook — immediate block | hook (Bash path) + pre-commit (commit path) |
|
|
105
|
+
| Post-edit formatter / lint | `PostToolUse(Write\|Edit)` | `PostToolUse(Bash)` (partial) |
|
|
106
|
+
| Session completion check | `Stop` hook | `Stop` hook (same) |
|
|
107
|
+
|
|
108
|
+
## Known Limitations
|
|
109
|
+
|
|
110
|
+
### Native `apply_patch` bypasses hooks
|
|
111
|
+
|
|
112
|
+
Per [OpenAI Codex docs](https://developers.openai.com/codex/hooks):
|
|
113
|
+
|
|
114
|
+
> "Currently `PreToolUse` only supports Bash tool interception."
|
|
115
|
+
|
|
116
|
+
Codex's native `apply_patch` tool is routed through a separate `ApplyPatchHandler` (see [openai/codex#16732](https://github.com/openai/codex/issues/16732)) that never emits hook events. As a result:
|
|
117
|
+
|
|
118
|
+
- Phasegate cannot pre-block edits made through native `apply_patch`
|
|
119
|
+
- Violations surface at **pre-commit time** instead
|
|
120
|
+
- Feedback is delayed relative to the Claude Code experience
|
|
121
|
+
|
|
122
|
+
**Mitigation**: commit frequently (e.g., after each logical unit of work). This shortens the window between violation and detection.
|
|
123
|
+
|
|
124
|
+
### Bash-invoked `apply_patch` is fully covered
|
|
125
|
+
|
|
126
|
+
If the model invokes `apply_patch` via a Bash command (`apply_patch <<'PATCH' ... PATCH`), `PreToolUse(Bash)` fires and Phasegate's `BashWriteTargetExtractor` parses the heredoc to identify target files. This path is hard-blocked like any other Bash write.
|
|
127
|
+
|
|
128
|
+
### Windows is not supported
|
|
129
|
+
|
|
130
|
+
Codex hooks themselves do not support Windows. Phasegate follows the same constraint.
|
|
131
|
+
|
|
132
|
+
### `unified_exec` interception is incomplete
|
|
133
|
+
|
|
134
|
+
Codex documents that the newer `unified_exec` mechanism has incomplete interception. Commands routed through `unified_exec` may bypass hooks. Phasegate falls back to pre-commit for any such bypass.
|
|
135
|
+
|
|
136
|
+
## Recommended Workflow
|
|
137
|
+
|
|
138
|
+
1. **Enable all three layers**: Codex hooks + pre-commit hook + CI validation
|
|
139
|
+
2. **Commit frequently** to catch native apply_patch violations early
|
|
140
|
+
3. **Review the coverage matrix** above so you understand which edits are hard-blocked vs caught later
|
|
141
|
+
|
|
142
|
+
## Troubleshooting
|
|
143
|
+
|
|
144
|
+
### Hooks don't seem to run
|
|
145
|
+
|
|
146
|
+
- Verify `codex_hooks = true` is set in `config.toml`
|
|
147
|
+
- Verify `.codex/hooks.json` is in the project root or `~/.codex/`
|
|
148
|
+
- Run `codex --version` to ensure you're on a version that supports hooks
|
|
149
|
+
|
|
150
|
+
### False positives on Bash hooks
|
|
151
|
+
|
|
152
|
+
If non-write Bash commands are being blocked, check your `phasegate.config.json` `protectedFiles.exclude` list. You can also disable the `PostToolUse(Bash)` hook if lint runs too frequently.
|
|
153
|
+
|
|
154
|
+
### Native apply_patch violations slipped through
|
|
155
|
+
|
|
156
|
+
This is expected behavior until [openai/codex#16732](https://github.com/openai/codex/issues/16732) is fixed. The pre-commit layer will catch these at commit time. If immediate feedback is critical, consider instructing the model (via project-level context) to prefer Bash-based edits over native `apply_patch`.
|
|
157
|
+
|
|
158
|
+
## See Also
|
|
159
|
+
|
|
160
|
+
- [Claude Code Hooks Integration](./hooks-integration.md)
|
|
161
|
+
- [Phasegate Layer Model](./layer-model.md)
|
|
162
|
+
- [Codex Hooks Documentation (official)](https://developers.openai.com/codex/hooks)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Quick Mode vs Full Mode — Choosing the Right Flow
|
|
2
|
+
|
|
3
|
+
Phasegate ships two implementation flows. Picking the wrong one is the most common source of friction: Full on trivial changes feels overkill, and Quick on contract-level changes defeats the whole point of the harness. This guide gives you a decision flow and worked examples so the choice is mechanical, not judgemental.
|
|
4
|
+
|
|
5
|
+
> TL;DR — **Full Mode** (`/story-implementor`) is the default when a change touches API contracts, domain models, or new use cases. **Quick Mode** (`/quick-implementor`) is the escape hatch for bugfixes, docs, tests, and configuration tweaks. When in doubt, pick Full — a Full run on a small change is wasteful; a Quick run on a contract change is a latent bug.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Decision Flow
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
flowchart TD
|
|
13
|
+
start([Change request]) --> q1{Does it add or rename<br/>a public API / Port / CLI flag?}
|
|
14
|
+
q1 -- yes --> full[Use Full Mode<br/>/story-implementor]
|
|
15
|
+
q1 -- no --> q2{Does it add or rename<br/>a Domain Entity / VO / Aggregate?}
|
|
16
|
+
q2 -- yes --> full
|
|
17
|
+
q2 -- no --> q3{Does it introduce<br/>a new UseCase / workflow?}
|
|
18
|
+
q3 -- yes --> full
|
|
19
|
+
q3 -- no --> q4{Is it bugfix / docs / test /<br/>config / refactor-only?}
|
|
20
|
+
q4 -- yes --> quick[Use Quick Mode<br/>/quick-implementor]
|
|
21
|
+
q4 -- no --> review[Stop and reconsider:<br/>scope may be unclear]
|
|
22
|
+
review --> start
|
|
23
|
+
|
|
24
|
+
style full fill:#f9d5e5,stroke:#c81d6c
|
|
25
|
+
style quick fill:#d6f5d6,stroke:#2f9e44
|
|
26
|
+
style review fill:#fff3bf,stroke:#f59f00
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Rule of thumb**: if the change alters something another module can *observe* (contract, schema, domain shape, new capability), go Full. If the change is invisible to consumers (internal fix, doc rewording, test addition, config bump), go Quick.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Mode Comparison
|
|
34
|
+
|
|
35
|
+
| Aspect | Full Mode (`/story-implementor`) | Quick Mode (`/quick-implementor`) |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| Prerequisite check | `/implementation-readiness-checker` required | Not required |
|
|
38
|
+
| Phase Gate | Enforced — `logical_design.md` + `domain_model.md` must exist | Relaxed — design docs not required |
|
|
39
|
+
| 2-Phase execution | Phase 1 (plan) → approval → Phase 2 (TDD) | Single phase |
|
|
40
|
+
| TDD pyramid | Unit → IT → E2E in order | Fix + spot-test only |
|
|
41
|
+
| Test design doc | Required before coding | Not required |
|
|
42
|
+
| Coverage target | 90% or above | Existing coverage maintained |
|
|
43
|
+
| L1 Biome rules | All 8 rules | **All 8 rules** |
|
|
44
|
+
| L2 Pre-commit | phase-gate + metadata + test-quality | **metadata + test-quality** (phase-gate relaxed) |
|
|
45
|
+
| L3 CI | security + performance + coverage + nyquist | security only |
|
|
46
|
+
| L4 Scheduled | drift + consistency + dead-code | skipped |
|
|
47
|
+
| Commit prefix | conventional (`feat:`, `fix:`, ...) | `[quick] ...` |
|
|
48
|
+
|
|
49
|
+
Both modes keep **L1 in full strength** and **L2 metadata / test-quality** — `@unit` / `@layer` comments and AAA test structure are non-negotiable regardless of flow.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Worked Examples
|
|
54
|
+
|
|
55
|
+
### Full Mode candidates
|
|
56
|
+
|
|
57
|
+
| Change | Why Full |
|
|
58
|
+
|---|---|
|
|
59
|
+
| Add a new `/phasegate inspect-unit` CLI command | New public surface — downstream users will depend on it |
|
|
60
|
+
| Introduce a `ValidationReport` value object | New domain model; invariants must be designed up front |
|
|
61
|
+
| Split a monolithic `PhaseGate` aggregate into two | Domain shape change — ripples into tests and consumers |
|
|
62
|
+
| Add a new "scheduled-audit" UseCase | New workflow requires logical design + test design |
|
|
63
|
+
| Change a Port interface (adapter contract) | Breaks existing adapters; contract change by definition |
|
|
64
|
+
|
|
65
|
+
### Quick Mode candidates
|
|
66
|
+
|
|
67
|
+
| Change | Why Quick |
|
|
68
|
+
|---|---|
|
|
69
|
+
| Fix a NaN in `calculate-coverage-usecase.ts` | Bugfix in existing code; no contract change |
|
|
70
|
+
| Reword an error message in a Biome rule | User-visible but not semantically new |
|
|
71
|
+
| Add a missing test case for an existing branch | Test-only; no production code touched |
|
|
72
|
+
| Bump `vitest` to a patch version in `package.json` | Config / dependency change |
|
|
73
|
+
| Rename a local helper variable across one file | Refactor with no external effect |
|
|
74
|
+
| Update `docs/guide/*.md` for clarity | Pure documentation |
|
|
75
|
+
| Add a new regex pattern to an existing `protectedFiles.exclude` list | Config tweak |
|
|
76
|
+
|
|
77
|
+
### Ambiguous — default to Full
|
|
78
|
+
|
|
79
|
+
| Change | Why not Quick |
|
|
80
|
+
|---|---|
|
|
81
|
+
| "Small" new feature, "just one function" | New behaviour is a contract addition; Quick would skip the test design gate |
|
|
82
|
+
| Refactor that moves types between modules | Import graph changes can cascade; Full's L3 coverage/performance gates catch regressions |
|
|
83
|
+
| "Tiny" adapter change that only adds one method | Port surface change — contract change even if code is short |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Two-Tier Operation for Solo / Small Projects
|
|
88
|
+
|
|
89
|
+
Running every change through Full AIDLC is genuinely heavy for one-person projects. A pragmatic pattern is the **core / periphery split**:
|
|
90
|
+
|
|
91
|
+
- **Core scope** — the parts of the system where correctness, contracts, or domain invariants matter. Always Full.
|
|
92
|
+
- **Periphery scope** — CLI glue, helper utilities, documentation, developer tooling, scheduled jobs that aren't in the hot path. Default to Quick, escalate to Full only when a change touches a contract.
|
|
93
|
+
|
|
94
|
+
### Example partitioning (from the Phasegate repo itself)
|
|
95
|
+
|
|
96
|
+
| Scope | Typical path | Default mode |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| Core | `scripts/harness/<unit>/domain/**`, Port interfaces, public CLI surface | Full |
|
|
99
|
+
| Core | `docs/product/construction/<unit>/*.md` (contract docs) | Full |
|
|
100
|
+
| Periphery | Internal helpers in `application/` that don't change ports | Quick-first, Full if contract impact emerges |
|
|
101
|
+
| Periphery | `scripts/harness/presentation/` formatting / wording | Quick |
|
|
102
|
+
| Periphery | `docs/guide/*`, `README.md`, `.claude/skills/*` tweaks | Quick |
|
|
103
|
+
| Periphery | Version bumps, `phasegate.config.json` value edits | Quick |
|
|
104
|
+
|
|
105
|
+
Codify the split in your head (or in a project CLAUDE.md note) — "`domain/**` is core, everything else starts Quick" is a healthy default for a single-maintainer project.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Common Pitfalls
|
|
110
|
+
|
|
111
|
+
1. **Using Quick to dodge a Phase Gate block.** If pre-tool-use blocks your write because `logical_design.md` is missing, the correct response is to create the design doc, not to re-launch in Quick Mode. Quick Mode is for changes that genuinely don't need design — not for bypassing the gate.
|
|
112
|
+
2. **Declaring "bugfix" on what is really a new feature.** Adding a new branch to an existing function that handles a previously-unsupported case is a feature, not a bugfix. If consumers will see new behaviour they didn't see before, it is Full Mode material.
|
|
113
|
+
3. **Drawing the core/periphery line too generously.** "Periphery" should mean "cannot affect contracts or domain invariants." If you're unsure, treat it as core for this change — you can re-classify later.
|
|
114
|
+
4. **Batching a Full change and a Quick change in the same commit.** If a commit touches both a domain model and a doc typo, run Full — the `[quick]` prefix on a commit that also changes a domain file is misleading.
|
|
115
|
+
5. **Using Quick for multi-Unit changes.** Cross-Unit work implies contract coordination; that is Full territory by definition.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## FAQ
|
|
120
|
+
|
|
121
|
+
**Q. I have a one-line bugfix in `domain/`. Does "any file under `domain/`" auto-trigger Full?**
|
|
122
|
+
Not mechanically — Quick Mode does not inspect paths. A one-line bugfix inside an existing domain method (fixing an off-by-one, null check, wrong comparator) is still Quick-eligible. What triggers Full is *adding or reshaping* a domain concept, not editing an existing one.
|
|
123
|
+
|
|
124
|
+
**Q. What if Quick discovers the change is bigger than expected mid-flight?**
|
|
125
|
+
Stop, commit nothing, and re-launch `/story-implementor`. Don't try to "finish in Quick" — you'll skip the design gate that would otherwise catch the scope creep.
|
|
126
|
+
|
|
127
|
+
**Q. Can I disable Quick Mode entirely?**
|
|
128
|
+
Yes — remove all entries from `quickMode.allowedCategories` in `phasegate.config.json`. All changes will route through Full Mode. This is reasonable for high-compliance projects.
|
|
129
|
+
|
|
130
|
+
**Q. Can I add custom categories?**
|
|
131
|
+
No. `allowedCategories` is a fixed enum (`bugfix`, `docs`, `test`, `config`). If your workflow needs a fifth category, that is evidence the change is probably Full Mode material.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Related
|
|
136
|
+
|
|
137
|
+
- [Skills Overview](skills-overview.md) — full catalogue of 28 skills
|
|
138
|
+
- [Layer Model](layer-model.md) — L0 through L4 defence layers
|
|
139
|
+
- [Configuration](configuration.md) — `quickMode` configuration reference
|
|
140
|
+
- `.claude/skills/quick-implementor/SKILL.md` — the Quick Mode skill definition
|
|
141
|
+
- `.claude/skills/story-implementor/SKILL.md` — the Full Mode skill definition
|
package/package.json
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* - `touch`
|
|
17
17
|
* - 複合コマンド (`&&`, `;`, `||`) とパイプ (`|`) 分割
|
|
18
18
|
* - ダブル/シングルクォート対応
|
|
19
|
+
* - `apply_patch` ヒアドキュメント (`*** Begin Patch` / `*** End Patch` ブロック内の
|
|
20
|
+
* `*** Update|Add|Delete File: <path>` 行) — Codex CLI 対応 (ISSUE-013 Wave 1)
|
|
19
21
|
*/
|
|
20
22
|
|
|
21
23
|
/** 引数トークン (値とクォート種別) */
|
|
@@ -219,6 +221,56 @@ function extractFromSingleCommand(tokens: Token[]): string[] {
|
|
|
219
221
|
return results;
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
/** apply_patch ブロック境界マーカー (Begin/End) */
|
|
225
|
+
const APPLY_PATCH_BEGIN_SOURCE = String.raw`\*\*\*\s+Begin\s+Patch`;
|
|
226
|
+
const APPLY_PATCH_END_SOURCE = String.raw`\*\*\*\s+End\s+Patch`;
|
|
227
|
+
/** ブロック内のファイル行: `*** (Update|Add|Delete) File: <path>` */
|
|
228
|
+
const APPLY_PATCH_FILE_LINE_SOURCE = String.raw`^\s*\*\*\*\s+(?:Update|Add|Delete)\s+File:\s*(.+?)\s*$`;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* apply_patch ヒアドキュメント構文から対象ファイルパスを抽出する。
|
|
232
|
+
*
|
|
233
|
+
* Codex CLI 等が採用する unified-diff 風パッチフォーマット:
|
|
234
|
+
* *** Begin Patch
|
|
235
|
+
* *** Update File: <path>
|
|
236
|
+
* *** Add File: <path>
|
|
237
|
+
* *** Delete File: <path>
|
|
238
|
+
* *** End Patch
|
|
239
|
+
*
|
|
240
|
+
* `*** End Patch` が欠けている場合は command 末尾までをブロックとして扱う
|
|
241
|
+
* (保護側に倒す — phase-gate の取りこぼしよりも誤検出のほうが許容される)。
|
|
242
|
+
*/
|
|
243
|
+
function extractApplyPatchTargets(command: string): string[] {
|
|
244
|
+
const beginGlobal = new RegExp(APPLY_PATCH_BEGIN_SOURCE, 'g');
|
|
245
|
+
const beginStarts: number[] = [];
|
|
246
|
+
let m: RegExpExecArray | null;
|
|
247
|
+
while ((m = beginGlobal.exec(command)) !== null) {
|
|
248
|
+
beginStarts.push(m.index + m[0].length);
|
|
249
|
+
}
|
|
250
|
+
if (beginStarts.length === 0) return [];
|
|
251
|
+
|
|
252
|
+
const endGlobal = new RegExp(APPLY_PATCH_END_SOURCE, 'g');
|
|
253
|
+
const endStarts: number[] = [];
|
|
254
|
+
while ((m = endGlobal.exec(command)) !== null) {
|
|
255
|
+
endStarts.push(m.index);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const results: string[] = [];
|
|
259
|
+
for (let i = 0; i < beginStarts.length; i += 1) {
|
|
260
|
+
const start = beginStarts[i];
|
|
261
|
+
const nextBegin = i + 1 < beginStarts.length ? beginStarts[i + 1] : command.length;
|
|
262
|
+
const endInRange = endStarts.find((e) => e > start && e <= nextBegin);
|
|
263
|
+
const end = endInRange ?? nextBegin;
|
|
264
|
+
const body = command.slice(start, end);
|
|
265
|
+
|
|
266
|
+
const fileRegex = new RegExp(APPLY_PATCH_FILE_LINE_SOURCE, 'gm');
|
|
267
|
+
while ((m = fileRegex.exec(body)) !== null) {
|
|
268
|
+
results.push(m[1]);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return results;
|
|
272
|
+
}
|
|
273
|
+
|
|
222
274
|
export class BashWriteTargetExtractor {
|
|
223
275
|
/**
|
|
224
276
|
* Bash コマンド文字列から書き込み先ファイルパスを抽出する。
|
|
@@ -243,6 +295,14 @@ export class BashWriteTargetExtractor {
|
|
|
243
295
|
}
|
|
244
296
|
}
|
|
245
297
|
|
|
298
|
+
// apply_patch ヒアドキュメント対応 (ISSUE-013 Wave 1)
|
|
299
|
+
// 既存の token ベース抽出では heredoc body 内のマーカー行を拾えないため、
|
|
300
|
+
// raw command 文字列から独立にスキャンする。
|
|
301
|
+
const applyPatchTargets = extractApplyPatchTargets(command);
|
|
302
|
+
for (const p of applyPatchTargets) {
|
|
303
|
+
collected.push(p);
|
|
304
|
+
}
|
|
305
|
+
|
|
246
306
|
// 重複除去 (挿入順保持)
|
|
247
307
|
const seen = new Set<string>();
|
|
248
308
|
const unique: string[] = [];
|