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.
Files changed (52) hide show
  1. package/README.ja.md +32 -0
  2. package/README.md +33 -0
  3. package/docs/guide/codex-integration.md +162 -0
  4. package/docs/guide/quick-vs-full-mode.md +141 -0
  5. package/package.json +1 -1
  6. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +60 -0
  7. package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +299 -0
  8. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +54 -0
  9. package/scripts/harness/agent-integration/presentation/user-prompt-submit-hook.ts +70 -0
  10. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +15 -0
  11. package/scripts/harness/integrations/pre-commit.ts +128 -28
  12. package/scripts/harness/main.ts +87 -9
  13. package/scripts/harness/phase2-extensions/application/dto/check-initial-creation-expiration-input.ts +9 -0
  14. package/scripts/harness/phase2-extensions/application/dto/check-initial-creation-expiration-output.ts +17 -0
  15. package/scripts/harness/phase2-extensions/application/usecases/check-initial-creation-expiration-usecase.ts +103 -0
  16. package/scripts/harness/phase2-extensions/composition-root.ts +22 -0
  17. package/scripts/harness/phase2-extensions/domain/aggregates/initial-creation-expiration-rule.ts +103 -0
  18. package/scripts/harness/phase2-extensions/domain/ports/frontmatter-reader-port.ts +17 -0
  19. package/scripts/harness/phase2-extensions/domain/ports/initial-creation-age-port.ts +9 -0
  20. package/scripts/harness/phase2-extensions/domain/ports/initial-creation-expiration-config-port.ts +9 -0
  21. package/scripts/harness/phase2-extensions/domain/services/initial-creation-expiration-check-service.ts +54 -0
  22. package/scripts/harness/phase2-extensions/domain/value-objects/initial-creation-age.ts +54 -0
  23. package/scripts/harness/phase2-extensions/infrastructure/adapters/git-log-initial-creation-age-adapter.ts +77 -0
  24. package/scripts/harness/phase2-extensions/infrastructure/adapters/harness-config-initial-creation-expiration-adapter.ts +57 -0
  25. package/scripts/harness/phase2-extensions/infrastructure/adapters/markdown-frontmatter-reader-adapter.ts +56 -0
  26. package/scripts/harness/phase2-extensions/presentation/formatters/initial-creation-expiration-result-formatter.ts +23 -0
  27. package/scripts/harness/phase2-extensions/presentation/handlers/check-initial-creation-expiration-handler.ts +38 -0
  28. package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +20 -0
  29. package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +83 -0
  30. package/scripts/harness/quick-mode/composition-root.ts +12 -0
  31. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +38 -32
  32. package/scripts/harness/quick-mode/domain/value-objects/quick-mode-config.ts +36 -4
  33. package/scripts/harness/quick-mode/infrastructure/adapters/harness-config-quick-mode-config-adapter.ts +6 -0
  34. package/scripts/harness/quick-mode/presentation/formatters/change-category-formatter.ts +42 -0
  35. package/scripts/harness/quick-mode/presentation/handlers/check-change-category-handler.ts +50 -0
  36. package/scripts/harness/setup/skill-deployer.ts +30 -0
  37. package/scripts/harness/traceability-model/composition-root.ts +14 -0
  38. package/scripts/harness/traceability-model/domain/value-objects/project-relative-path.ts +3 -0
  39. package/scripts/harness/traceability-model/infrastructure/parsers/markdown-story-annotation-parser.ts +39 -4
  40. package/scripts/harness/traceability-model/presentation/cli/validate-metadata-command-handler.ts +103 -9
  41. package/skills/domain-designer/SKILL.md +34 -0
  42. package/skills/it-test-logic-designer/SKILL.md +16 -0
  43. package/skills/logical-designer/SKILL.md +34 -0
  44. package/skills/quick-implementor/SKILL.md +10 -1
  45. package/skills/scenario-test-logic-designer/SKILL.md +16 -0
  46. package/skills/story-implementor/SKILL.md +58 -0
  47. package/skills/unit-designer/SKILL.md +41 -0
  48. package/skills/unit-test-logic-designer/SKILL.md +18 -0
  49. package/templates/.codex/hooks.json +63 -0
  50. package/templates/logical_design.template.md +79 -0
  51. package/templates/source.template.ts +18 -0
  52. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phasegate",
3
- "version": "0.44.0",
3
+ "version": "0.63.0",
4
4
  "packageManager": "pnpm@10.30.1",
5
5
  "description": "Phasegate — AI-agnostic quality defense toolkit. Enforces structural integrity between design intent and code.",
6
6
  "license": "Apache-2.0",
@@ -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[] = [];