phasegate 0.335.0 → 0.340.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 (59) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.ja.md +22 -9
  3. package/README.md +28 -17
  4. package/docs/ADR/038-config-state-operation-permission-policy.md +5 -2
  5. package/docs/ADR/041-non-excludable-agent-trust-roots.md +68 -0
  6. package/docs/guide/antigravity-integration.md +26 -0
  7. package/docs/guide/cli-reference.md +4 -4
  8. package/docs/guide/codex-integration.md +44 -107
  9. package/docs/guide/grok-integration.md +26 -0
  10. package/docs/guide/hooks-integration.md +27 -4
  11. package/docs/guide/installation.md +4 -2
  12. package/docs/guide/setup-artifacts.md +4 -4
  13. package/docs/guide/skills-overview.md +1 -1
  14. package/package.json +1 -1
  15. package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +1 -1
  16. package/scripts/harness/agent-integration/application/dto/normalized-pre-tool-use-request.ts +32 -0
  17. package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +2 -2
  18. package/scripts/harness/agent-integration/domain/ports/full-mode-requirement-query-port.ts +3 -1
  19. package/scripts/harness/agent-integration/domain/services/apply-patch-write-target-extractor.ts +98 -0
  20. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +6 -52
  21. package/scripts/harness/agent-integration/domain/value-objects/hook-translation-result.ts +1 -1
  22. package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +35 -18
  23. package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +1 -1
  24. package/scripts/harness/agent-integration/presentation/post-tool-use-hook.ts +1 -0
  25. package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +123 -70
  26. package/scripts/harness/agent-integration/presentation/pre-tool-use-payload-normalizer.ts +228 -0
  27. package/scripts/harness/agent-integration/presentation/pre-tool-use-response-renderer.ts +38 -0
  28. package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +2 -0
  29. package/scripts/harness/installation/application/checks/antigravity-hook-missing-check.ts +79 -0
  30. package/scripts/harness/installation/application/checks/codex-hook-missing-check.ts +70 -6
  31. package/scripts/harness/installation/application/checks/grok-hook-missing-check.ts +79 -0
  32. package/scripts/harness/installation/application/checks/husky-runtime-inactive-check.ts +33 -0
  33. package/scripts/harness/installation/application/named-hook-json.ts +17 -0
  34. package/scripts/harness/installation/application/operator-notice.ts +42 -0
  35. package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +18 -7
  36. package/scripts/harness/installation/application/usecases/run-install.ts +152 -52
  37. package/scripts/harness/installation/application/usecases/run-reconcile.ts +86 -10
  38. package/scripts/harness/installation/application/usecases/run-uninstall.ts +149 -25
  39. package/scripts/harness/installation/composition-root.ts +10 -0
  40. package/scripts/harness/installation/domain/agent-target.ts +39 -0
  41. package/scripts/harness/installation/domain/check-id.ts +5 -0
  42. package/scripts/harness/installation/domain/husky-runtime-state.ts +34 -0
  43. package/scripts/harness/installation/domain/ports/git-hooks-runtime-probe.ts +9 -0
  44. package/scripts/harness/installation/domain/repair-table.ts +5 -0
  45. package/scripts/harness/installation/infrastructure/adapters/git-hooks-runtime-probe-adapter.ts +62 -0
  46. package/scripts/harness/installation/presentation/cli/install-handler.ts +23 -4
  47. package/scripts/harness/installation/presentation/cli/reconcile-handler.ts +7 -1
  48. package/scripts/harness/installation/presentation/formatters/diagnostic-report-formatter.ts +27 -0
  49. package/scripts/harness/main.ts +100 -39
  50. package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +1 -1
  51. package/scripts/harness/quick-mode/application/dto/quick-mode-eligibility-contract.ts +1 -1
  52. package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +3 -1
  53. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +13 -2
  54. package/scripts/harness/quick-mode/domain/types/rejection-rule.ts +1 -1
  55. package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +13 -3
  56. package/templates/.agents/hooks.json +16 -0
  57. package/templates/.claude/scripts/analyze-errors-hook.sh +2 -2
  58. package/templates/.claude/settings.json +5 -3
  59. package/templates/.codex/hooks.json +2 -2
package/CHANGELOG.md CHANGED
@@ -9,12 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
 
12
+ - **WI-385 — Grok Build / Antigravity pre-edit integration** — PreToolUse now detects flat snake_case, flat camelCase, and nested `toolCall` payloads structurally, maps Grok and Antigravity write vocabularies into the existing gate, and renders runtime-specific deny JSON without changing Claude/Codex stdout contracts. Install/init/setup/doctor accept `grok`, `antigravity`, and `all` while preserving `both=claude+codex`; lifecycle management adds the Antigravity named hook map, Grok/Antigravity structural doctor checks, trust/CLI-only notices, and explicit L2 backstop guidance. <!-- @work-item-id WI-385 -->
13
+
12
14
  - **WI-335 — エラー案内の機械往復保証(remediationType 分類 + round-trip テスト)** — suggested action が本当に「従えば直る」かを人間レビュー頼みにせず CI で保証する仕組み。HarnessError に optional `remediationType`(mechanical / ai-assisted / manual、未設定は manual 扱い)を導入し、代表 validator を分類(L2-002 metadata=mechanical、L3-003 レポート不在=mechanical・閾値未達=ai-assisted、L3-001=manual、L4-001/002=ai-assisted)。mechanical 宣言されたエラーは「エラー → suggestion 文言を機械適用 → 再実行 → pass」の往復テストで固定し、案内文言と実挙動が乖離すると(#37/#39 型の破れ)テストが落ちる構造にした。
13
15
 
14
16
  - **WI-329 — 実分布リリースゲート(tarball release-smoke)** — 単体テスト全 green でも新規インストール即クラッシュ(#34)・非 TS リポで fail-closed(#37/#39)・dead flag(#36)がすり抜けた教訓から、`npm pack` した tarball を実分布相当 fixture(純 Python / Go monorepo / docs のみ)にクリーンインストールし install → doctor → validate → uninstall を実走する E2E を追加。通常 suite では skip(`PHASEGATE_RELEASE_SMOKE=1` ガードで hermetic 性維持)し、CI の新 job `release-smoke` が pack job の実バイト列 artifact に対して実行する。`--with-husky` のフラグ有効性 assert で dead-flag 再発も検知。
15
17
 
16
18
  ### Fixed
17
19
 
20
+ - **WI-390 — GitHub #47–#50 の hook / doctor / Quick Mode / trust-root 修正** — Biome の JavaScript formatter を single quote に固定し、Claude PostToolUse analyze hook を raw Biome から project-wide `phasegate lint` へ統一。doctor は `core.hooksPath` と Husky v8/v9 shim の実効状態を検査する。配置場所を問わず `.md` / `.mdx` を docs に分類し、単一の不許可カテゴリは `CATEGORY_NOT_ALLOWED`、複数カテゴリは `MIXED_CHANGES` として区別する。config・baseline・Husky runtime・root agent instructions を `protectedFiles.exclude` で解除できない trust root に格上げし、config 不在/不正時も direct Write/Edit を遮断する。 <!-- @work-item-id WI-390 -->
21
+
18
22
  - **WI-334 — CI workflow ファイルの change-category 分類取りこぼしを修正** — `.github/workflows/*.yml` の新規作成が CREATE→feature フォールバックに落ちて pre-tool-use hook にブロックされ、かつ .github/ は unit を持たないため案内される story-implementor 経路が構造的に完遂不能だった(WI-329 のドッグフードで発見。MODIFY は bugfix で通るため防御としても不整合)。WI-261(skills/**/*.md → docs)と同型の明示ルールで `.github/workflows/` 配下の yml/yaml を config に分類(内容防御は L3-006 + integrity pin が担当)。併せて CLI `check-change-category` の changeKind をファイル存在で推定し hook 判定と一致させた(hook の Bash 経路は従来挙動を完全維持)。
19
23
 
20
24
  - **WI-333 — config 不在時の hook 全遮断デッドロックを解消(ADR-038 G1 / GitHub #40 完全解消)** — config **不在**(ENOENT)で pre-tool-use hook が未捕捉例外→exit 2 となり、config を作成する Write すら遮断される自己修復デッドロックが missing 状態に残っていた(WI-314 は invalid のみ対応)。hook 用 config adapter で ENOENT を警告+既定値の fail-open に変更(EACCES 等の真の異常は従来どおり throw)。gated パスへの書き込みは phase-gate 側が config-foundation 経由の独立 load で fail-closed を維持することをテストで固定。ADR-038 の許可表と G1 を解消済みに更新。
package/README.ja.md CHANGED
@@ -83,7 +83,7 @@ claude
83
83
 
84
84
  - `phasegate.config.json` — 品質設定の Single Source of Truth
85
85
  - `skills/` — 29 の AIDLC スキル一式
86
- - `.claude/skills/` ・ `.codex/skills/` — agent 向けの skill symlink
86
+ - `.claude/skills/` ・ `.codex/skills/` ・ `.agents/skills/` — agent 向けの skill symlink
87
87
  - `.claude/settings.json` — PreToolUse / PostToolUse / Stop hook
88
88
  - `.codex/hooks.json` — Codex CLI hooks 設定(`--agent codex|both` 時)
89
89
  - `docs/principles/*.md` — アーキテクチャ哲学・テスト規約(immutable)
@@ -134,7 +134,7 @@ npx phasegate install --personal --agent claude --apply
134
134
  | **作るファイル** | `.phasegate-local/phasegate.config.json`(ローカル専用 config)/ runtime から見えるローカル agent context(Claude は `.claude/CLAUDE.md`、Codex は root の `AGENTS.md` が不在または既に PhaseGate 管理下のときのみ `AGENTS.md`)/ `.claude/settings.json` + `.claude/skills/` または `.codex/hooks.json` + `.codex/skills/`(選択した agent の runtime artifact)/ `.git/hooks/pre-commit` + `.git/hooks/commit-msg`(ローカル git hook)/ `.phasegate-local/docs/`(設計原則文書コピー)/ `.phasegate/manifest.json` |
135
135
  | **既存 skills の扱い** | 個人用 skills directory がある場合は merge — bundled skills を refresh し、user 所有の skill は保持する |
136
136
  | **コミット漏れ対策** | `.git/info/exclude` にローカル専用 block を管理して、個人用ファイルが誤ってチームの commit に混ざらないようにする。commit 時の L2 防御は `.git/hooks/` で発火する |
137
- | **Codex hook flag** | user-level feature flag の有効化は手動アクションとして残る(`codex features enable hooks`) |
137
+ | **Codex hook trust** | Codex CLI >= 0.124.0 では hooks は stable / default-on。`.codex/hooks.json` 更新後は `/hooks` で current definition hash を再 trust する |
138
138
 
139
139
  チーム所有の `AGENTS.md` が既に存在する場合、Codex の personal install はそれを変更せず、`doctor --personal --agent codex` が残りの context ステップを(`AGENTS.override.md` に隠すのではなく)報告します。Codex を併用する場合は `--agent codex` または `--agent both` を指定します。アンインストールは team install と同様に `npx phasegate uninstall --apply` を使えば manifest 経由でローカル成果物のみが除去されます。<!-- @work-item-id WI-207 --> <!-- @work-item-id WI-208 --> <!-- @work-item-id WI-209 --> <!-- @work-item-id WI-213 --> <!-- @work-item-id WI-215 -->
140
140
 
@@ -159,11 +159,22 @@ npx phasegate reconcile --apply
159
159
  ### Codex CLI を使う場合
160
160
 
161
161
  ```bash
162
- npx phasegate init --name my-project --agent codex --with-husky
163
- codex features enable hooks # Codex 本体の feature flag を手動で有効化
162
+ npx phasegate install --agent codex --with-husky --apply
163
+ npx phasegate doctor --agent codex
164
164
  ```
165
165
 
166
- 両方使う場合は `--agent both`。Codex のネイティブ `apply_patch` は現時点で事前 hook を発火しないため、pre-commit (L2) commit 時にブロックします。Bash 経由の書き込みは実行前に止まります。詳細は [Codex Integration Guide](docs/guide/codex-integration.md) を参照。
166
+ 両方使う場合は `--agent both`。Codex CLI >= 0.124.0 ではネイティブ `apply_patch` Update/Add/Delete も編集前 hook に入り、違反を hard block します。`.codex/hooks.json` 更新後は `/hooks` で definition hash を再 trust してください。pre-commit (L2) backstop として維持します。詳細は [Codex Integration Guide](docs/guide/codex-integration.md) を参照。<!-- @work-item-id WI-384 -->
167
+
168
+ ### Grok Build / Antigravity CLI を使う場合
169
+
170
+ ```bash
171
+ npx phasegate install --agent grok --apply
172
+ npx phasegate doctor --agent grok
173
+ npx phasegate install --agent antigravity --apply
174
+ npx phasegate doctor --agent antigravity
175
+ ```
176
+
177
+ Grok は hooks 対応の CLI 1.0.0 系(検証対象)が最低要件です。Claude compatibility scanner を使うため、Phasegate は `.claude/settings.json` と `.claude/skills` を管理し、二重発火する `.grok/hooks` は作りません。hook が静かに効かない場合は `grok inspect`、`/hooks`、`--trust` または `/hooks-trust` で load / trust を確認してください。Antigravity hooks は CLI v1.0.14 以降が最低要件で、Phasegate は `agy` 1.1.x で検証しています。`.agents/hooks.json` の named `phasegate-gate` と `.agents/skills` を使い、静かに効かない場合は `agy` の `/hooks` で load を確認します。編集前 hard block の対応範囲は `agy` CLI で、IDE / desktop の hook 発火は保証しません。その範囲では L2 pre-commit が主防御です。全 runtime は `--agent all`、従来の `both` は Claude + Codex のままです。詳細は [Grok guide](docs/guide/grok-integration.md) と [Antigravity guide](docs/guide/antigravity-integration.md) を参照してください。<!-- @work-item-id WI-385 -->
167
178
 
168
179
  ### アップデート
169
180
 
@@ -185,7 +196,7 @@ npx phasegate reconcile --apply
185
196
  | **5 層バリデーション (L0-L4)** | エディタ保存 → pre-commit → CI → 週次まで段階的に品質チェック |
186
197
  | **29 AIDLC スキル** | 要求定義 → ドメイン設計 → テスト設計 → TDD 実装をスキルとして提供 |
187
198
  | **Quick Mode** | バグ修正・docs・テスト追加など軽微変更ではゲートを緩和して高速化 |
188
- | **Claude Code / Codex Hooks** | Write/Edit/Bash 時に自動でゲートチェック・lint を実行 |
199
+ | **複数 runtime hooks** | Claude Code / Codex / Grok Build / Antigravity CLI の payload を形状で判定し編集前 gate を実行 |
189
200
  | **HarnessError 形式** | 全エラーに ADR 参照 + 修正例が含まれ、AI が自己修正できる |
190
201
  | **Baseline (retrofit)** | 既存リポジトリ導入時、`baseline` snapshot に登録した既存ファイルは構造的に編集されるまで gate 対象外 |
191
202
  | **カスタム gate** | AIDLC 以外のプロジェクトでも schema-first など独自の前提条件を設定できる |
@@ -462,15 +473,15 @@ npx phasegate <command> [options]
462
473
 
463
474
  ### Codex CLI
464
475
 
465
- `init --agent codex` で `.codex/hooks.json` を配置。Codex のネイティブ `apply_patch` ツールは hook を発火しないため([openai/codex#16732](https://github.com/openai/codex/issues/16732))、ネイティブ経路は **pre-commit (L2)** commit 時にブロックされます。
476
+ `install --agent codex --apply` で `.codex/hooks.json` を配置します。Codex CLI >= 0.124.0 の native `apply_patch` payload を受理し、全 target を既存 gate へ合流させます。hook definition 更新後は `/hooks` で再 trust が必要です。<!-- @work-item-id WI-384 -->
466
477
 
467
478
  | 編集経路 | 事前 hard block | commit 時 block |
468
479
  |---|---|---|
469
480
  | Bash 書き込み(`sed -i`, `tee`, heredoc, `cat >`) | ✅ PreToolUse(Bash) | ✅ pre-commit |
470
481
  | Bash 経由 `apply_patch <<'PATCH'` | ✅ PreToolUse(Bash) | ✅ pre-commit |
471
- | Codex ネイティブ `apply_patch` | Codex 側の制約で hook 非発火 | ✅ pre-commit |
482
+ | Codex ネイティブ `apply_patch` Update/Add/Delete | PreToolUse(apply_patch) | ✅ pre-commit |
472
483
 
473
- **推奨運用**: こまめに commit して pre-commit でネイティブ `apply_patch` 違反を早期に surface する。
484
+ PostToolUse(apply_patch) は既存 lint 経路を実行します。ローカル hook が未 trust / skip の場合に備え、pre-commit CI backstop / authoritative re-check として残します。
474
485
 
475
486
  詳細: [Hooks Integration](docs/guide/hooks-integration.md) ・ [Codex Integration](docs/guide/codex-integration.md)
476
487
 
@@ -613,6 +624,8 @@ L3 Nyquist Validation の `requirement-test-matrix.json` は `phasegate:generate
613
624
  - [5-Layer Defense Model](docs/guide/layer-model.md) — L0-L4 詳細・HarnessError 形式
614
625
  - [Hooks Integration](docs/guide/hooks-integration.md) — Claude Code Hooks 設定
615
626
  - [Codex Integration](docs/guide/codex-integration.md) — Codex CLI セットアップ・カバレッジ
627
+ - [Grok Integration](docs/guide/grok-integration.md) — Claude 互換 hook、payload 対応、trust 確認
628
+ - [Antigravity Integration](docs/guide/antigravity-integration.md) — `agy` CLI named hook、payload 対応、IDE / desktop 境界
616
629
  - [Quick Mode vs Full Mode](docs/guide/quick-vs-full-mode.md) — `/story-implementor` vs `/quick-implementor`
617
630
  - [Retrofit Adoption Guide](docs/guide/retrofit-adoption.md) — 既存リポジトリへの段階的導入
618
631
  - [Preset Selection Guide](docs/guide/preset-selection.md) — 3 系統の preset 選定
package/README.md CHANGED
@@ -84,7 +84,7 @@ claude
84
84
 
85
85
  - `phasegate.config.json` as the quality settings source of truth
86
86
  - `skills/` with 29 AIDLC skills
87
- - `.claude/skills` and/or `.codex/skills` links for agent use
87
+ - `.claude/skills`, `.codex/skills`, and/or `.agents/skills` links for agent use
88
88
  - `.claude/settings.json` and/or `.codex/hooks.json` hook configuration
89
89
  - `docs/principles/*.md` and `docs/folder_management_rules.md`
90
90
  - `.husky/pre-commit`, `.husky/commit-msg`, and `.husky/pre-push` when `--with-husky` is passed
@@ -143,11 +143,22 @@ npx phasegate reconcile --apply
143
143
  ### Codex CLI
144
144
 
145
145
  ```bash
146
- npx phasegate init --name my-project --agent codex --with-husky
147
- codex features enable hooks
146
+ npx phasegate install --agent codex --with-husky --apply
147
+ npx phasegate doctor --agent codex
148
148
  ```
149
149
 
150
- Use `--agent both` for projects that use Claude Code and Codex together. Codex native `apply_patch` currently cannot be intercepted before the edit, so those violations are caught at pre-commit; Bash-based writes are blocked before execution.
150
+ Use `--agent both` for projects that use Claude Code and Codex together. Codex CLI >= 0.124.0 emits hooks for native `apply_patch`, so Update/Add/Delete targets are hard-blocked before editing when they violate Phasegate rules. After `.codex/hooks.json` changes, open `/hooks` and trust the current definition hash. L2 pre-commit remains the backstop. <!-- @work-item-id WI-384 -->
151
+
152
+ ### Grok Build / Antigravity CLI
153
+
154
+ ```bash
155
+ npx phasegate install --agent grok --apply
156
+ npx phasegate doctor --agent grok
157
+ npx phasegate install --agent antigravity --apply
158
+ npx phasegate doctor --agent antigravity
159
+ ```
160
+
161
+ Grok requires the hook-capable CLI 1.0.0 series used for verification. It uses its Claude-compatible scanner: Phasegate manages `.claude/settings.json`, exposes skills through `.claude/skills`, and does not create a duplicate `.grok/hooks` source. If the hook is silently inactive, verify loading and trust with `grok inspect`, `/hooks`, and `--trust` or `/hooks-trust`. Antigravity hooks require CLI v1.0.14 or later; Phasegate verification targets `agy` 1.1.x. Antigravity uses the named `phasegate-gate` definition in `.agents/hooks.json` and project skills in `.agents/skills`; if it is silently inactive, confirm the loaded definition with `agy` `/hooks`. Pre-edit hard blocking is supported for the `agy` CLI surface; IDE/desktop hook execution is not guaranteed, so L2 pre-commit remains the primary backstop there. Use `--agent all` for every runtime; `both` intentionally remains Claude + Codex. See the [Grok](docs/guide/grok-integration.md) and [Antigravity](docs/guide/antigravity-integration.md) guides. <!-- @work-item-id WI-385 -->
151
162
 
152
163
  ### Update
153
164
 
@@ -169,7 +180,7 @@ npx phasegate reconcile --apply
169
180
  | **5-layer validation** | Runs checks from agent runtime and editor time through pre-commit, CI, and scheduled audits |
170
181
  | **29 AIDLC skills** | Guides AI agents through product architecture, story writing, domain design, test design, and TDD implementation |
171
182
  | **Quick Mode** | Keeps bugfixes, docs, test-only changes, and config changes lightweight while preserving traceability |
172
- | **Claude Code / Codex hooks** | Runs checks around Write/Edit/Bash operations and session boundaries |
183
+ | **Multi-runtime hooks** | Runs shape-based pre-edit checks for Claude Code, Codex, Grok Build, and Antigravity CLI |
173
184
  | **Agent-readable HarnessError output** | Gives AI agents the reason, missing artifacts, references, and examples needed to self-correct |
174
185
  | **Retrofit baseline** | Lets existing repositories adopt Phasegate gradually by grandfathering unchanged files |
175
186
  | **Configurable gates** | Supports AIDLC defaults or custom gates such as schema-first API development |
@@ -181,7 +192,7 @@ npx phasegate reconcile --apply
181
192
 
182
193
  ```
183
194
  +------------------------------------------------------------------+
184
- | L0 AGENT RUNTIME HOOKS Claude Code / Codex hooks |
195
+ | L0 AGENT RUNTIME HOOKS Claude / Codex / Grok / Antigravity |
185
196
  | PreToolUse (Write/Edit/Bash block + guide), PostToolUse |
186
197
  | (auto lint/format), Stop (ReentryGuard + complete-check), |
187
198
  | SessionStart, UserPromptSubmit. Plus Husky .husky/pre-commit |
@@ -551,28 +562,26 @@ Phasegate also integrates with [OpenAI Codex CLI](https://developers.openai.com/
551
562
  ### Quick setup
552
563
 
553
564
  ```bash
554
- # 1. Initialize the project for Codex (creates project-local files such as .codex/hooks.json and .codex/skills)
555
- npx phasegate init --name my-project --agent codex --with-husky
565
+ # 1. Install project-local Codex hooks and the pre-commit backstop
566
+ npx phasegate install --agent codex --with-husky --apply
556
567
 
557
- # 2. Enable the Codex CLI feature flag manually on your machine
558
- codex features enable hooks
568
+ # 2. Verify wiring, then trust the current definition in Codex /hooks
569
+ npx phasegate doctor --agent codex
559
570
  ```
560
571
 
561
572
  For dual-agent projects (Claude + Codex), use `--agent both`.
562
573
 
563
- `init` sets up files inside the project. The Codex CLI user-level hooks feature remains an explicit manual step.
564
-
565
- ### Coverage and known limitation
574
+ Codex CLI >= 0.124.0 is required. Hooks are stable and default-on, but a changed non-managed command hook must be re-trusted by definition hash through `/hooks`.
566
575
 
567
- 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.
576
+ ### Coverage
568
577
 
569
578
  | Path | Pre-edit hard block | Commit-time block |
570
579
  |---|---|---|
571
580
  | Shell writes (`sed -i`, `tee`, heredoc, `cat >`) | ✅ `PreToolUse(Bash)` | ✅ pre-commit |
572
581
  | Bash-invoked `apply_patch <<'PATCH'` | ✅ `PreToolUse(Bash)` (via `BashWriteTargetExtractor`) | ✅ pre-commit |
573
- | Native `apply_patch` tool call | not intercepted by Codex today | ✅ pre-commit |
582
+ | Native `apply_patch` Update/Add/Delete | `PreToolUse(apply_patch)` | ✅ pre-commit |
574
583
 
575
- **Recommended mitigation**: commit frequently (e.g., after each logical change) so native `apply_patch` violations surface quickly. See the full guide for details.
584
+ `PostToolUse(apply_patch)` runs the existing lint path. L2 pre-commit remains enabled as a backstop for untrusted or skipped local hooks. See the [Codex integration guide](docs/guide/codex-integration.md) for trust troubleshooting. <!-- @work-item-id WI-384 -->
576
585
 
577
586
  ---
578
587
 
@@ -588,7 +597,7 @@ README keeps only the entry points most users need. The full public/compatibilit
588
597
 
589
598
  | Command | Description |
590
599
  |---|---|
591
- | `init --name <name>` | Legacy-compatible bootstrap for new projects. Supports `--skills <core\|all>`, `--agent <claude\|codex\|both>`, `--with-husky`, `--with-ci`, and `--yes`. Prefer `install` when the project may already have hooks, scripts, or CI files. |
600
+ | `init --name <name>` | Legacy-compatible bootstrap for new projects. Supports `--skills <core\|all>`, `--agent <claude\|codex\|both\|grok\|antigravity\|all>`, `--with-husky`, `--with-ci`, and `--yes`. Prefer `install` when the project may already have hooks, scripts, or CI files. |
592
601
  | `install --dry-run` / `--apply` | Idempotently merge PhaseGate into the current project, preserve existing user content, add package scripts/devDependency, and write `.phasegate/manifest.json`. Use `--force` only for managed-file replacement. |
593
602
  | `doctor` | Diagnose silent or partial installations (`--json`, `--strict`, `--report-out <path>`). `--report-out` is an explicit file path, not `reporting.outputDir`. |
594
603
  | `uninstall --dry-run` / `--apply` | Remove PhaseGate-managed files and managed blocks using `.phasegate/manifest.json`, preserving user content. |
@@ -652,6 +661,8 @@ Detailed guides are available under `docs/guide/`:
652
661
  - [Contract Traceability](docs/guide/contract-traceability.md) -- `L2-015` public contract, boundary, error, state, and observation annotations
653
662
  - [Hooks Integration](docs/guide/hooks-integration.md) -- Claude Code Hooks setup and behavior
654
663
  - [Codex Integration](docs/guide/codex-integration.md) -- Codex CLI setup, coverage matrix, and native `apply_patch` limitation
664
+ - [Grok Integration](docs/guide/grok-integration.md) -- Claude-compatible hook setup, payload mapping, and trust checks
665
+ - [Antigravity Integration](docs/guide/antigravity-integration.md) -- `agy` CLI named hooks, payload mapping, and IDE/desktop boundary
655
666
  - [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
656
667
  - [Retrofit Adoption Guide](docs/guide/retrofit-adoption.md) -- Onboard an existing project without getting blocked: `init` → `baseline` → `scaffold-design` in 4 steps
657
668
 
@@ -9,6 +9,7 @@ date: 2026-07-18
9
9
 
10
10
  <!-- @work-item-id WI-330 -->
11
11
  <!-- @work-item-id WI-333 -->
12
+ <!-- @work-item-id WI-390 -->
12
13
 
13
14
  ## Context
14
15
 
@@ -41,7 +42,7 @@ config の解決順は project 直下 `phasegate.config.json` → `.phasegate-lo
41
42
 
42
43
  | 操作クラス \ config 状態 | valid | missing | invalid-json | invalid-schema |
43
44
  |---|---|---|---|---|
44
- | **config 自身への編集**(hook 経由 Write/Edit) | fail-open(既定では保護対象外。`protectedFiles.patterns` に含めた場合のみ CLI 誘導 block) | fail-open(WI-333。自己修復経路) | fail-open | fail-open |
45
+ | **config 自身への編集**(hook 経由 Write/Edit) | × protected-file block(WI-390 / ADR-041) | × protected-file block。bootstrap は managed CLI または人間の hook 外編集 | × protected-file block。hook / doctor 自体は fail-open | × protected-file block。doctor 完走後、人間が hook 外で修復 |
45
46
  | **gated パス書込**(`scripts/harness/` 等、hook 経由) | ● phase-gate 判定(fail-closed) | ● 既定設定で phase-gate 判定(fail-closed 維持、WI-333) | ● 既定設定で phase-gate 判定(fail-closed 維持) | ● 既定設定で phase-gate 判定(fail-closed 維持) |
46
47
  | **無関係パス書込**(hook 経由) | ○ | ○ fail-open(警告付き、WI-333) | ○ fail-open | ○ fail-open |
47
48
  | **無関係 Bash**(書込抽出なし、hook 経由) | ○ | ○ fail-open(警告付き、WI-333) | ○ fail-open(警告付き) | ○ fail-open(警告付き) |
@@ -53,7 +54,7 @@ config の解決順は project 直下 `phasegate.config.json` → `.phasegate-lo
53
54
  - **CLI dispatch 層の fail-open/fail-closed 分岐**: `scripts/harness/main.ts:1867` `CONFIG_FAIL_OPEN_COMMANDS = new Set(["hook", "doctor"])`、`main.ts:1869-1902` `loadResolvedConfig()` — `ConfigValidationError` は hook/doctor のみ fail-open・他は exit 2(`:1878-1889`)、`ConfigNotFoundError` は全コマンド silent fail-open(`:1891-1893`)、`ConfigParseError`(`instanceof ConfigPersistenceError`)は全コマンド警告付き fail-open(`:1894-1900`)。
54
55
  - **hook 実行層の fail-open**: `scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts` `loadConfig()` — JSON parse 失敗と `fs.readFileSync` の ENOENT(missing、WI-333)はいずれも警告 + 空 config(既定値)で続行。ENOENT **以外**の fs エラー(EACCES / EISDIR 等の真の異常)は従来どおり throw し、`scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts` の outer catch で「実行エラー」exit 2 になる。fallback config path は `pre-tool-use-hook.ts:58-76` `findConfigPath()`(不在時は `startDir/phasegate.config.json` を返す)。
55
56
  - **missing の gated パス fail-closed**: hook 側 config は既定値に縮退するが、gated パス書込は `phase-gate-query-adapter.ts` が config-foundation の `ConfigNotFoundError` を generic catch で「評価不能 = NOT passed」に落とすため、phase-gate block(フェーズゲート違反、exit 2)が維持される。
56
- - **config 自身が gated/protected でない根拠**: 既定の保護パターンに `phasegate.config.json` は含まれない(`scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts:17-27` `DEFAULT_PATTERNS`)。ユーザーが `protectedFiles.patterns` で保護した場合のみ CLI 誘導付き block(`handle-pre-tool-use-usecase.ts:480-495`)。
57
+ - **config 自身の non-excludable protection(WI-390)**: `phasegate.config.json` と personal config は ADR-041 trust root pattern であり、`protectedFiles.exclude` より先に合成される。hook / doctor の config load fail-open と direct mutation authorization を分離し、agent Write/Edit は全 config 状態で block する。
57
58
  - **doctor の config 状態可視化(WI-330 で追加)**: `scripts/harness/installation/infrastructure/adapters/config-status-probe-adapter.ts`(分類)、`installation/application/checks/config-status-check.ts`(missing → warn / invalid-* → red)、`installation/presentation/formatters/diagnostic-report-formatter.ts`(JSON `configStatus` フィールドと human `Config:` 行)。
58
59
 
59
60
  ### 3. 設計原則
@@ -61,6 +62,7 @@ config の解決順は project 直下 `phasegate.config.json` → `.phasegate-lo
61
62
  1. **自己修復例外は復旧経路の保証であり、検査系の fail-closed は緩めない。** hook(エージェントのツール遮断点)と doctor(自己診断)は config がどんな状態でも起動・完走できなければならない。逆に `validate` / `ci-check` 等の検査系は、設定が壊れた状態の検査結果を「合格」として流通させないため fail-closed を原則とする。
62
63
  2. **fail-open は必ず可視化とセットにする。** fail-open で既定設定に落ちた事実は stderr 警告(CLI/hook)と doctor の `configStatus` + `config-status` finding(missing = warn、invalid-* = red)で必ず表面化させる。「不正 config でも doctor GREEN」は本 ADR をもって仕様違反である。
63
64
  3. **gated スコープの fail-closed は config 状態に依存しない。** config が壊れていても、gated パスへの書込は既定設定による phase-gate 判定で引き続きブロックされる(fail-open は「遮断の解除」ではなく「既定設定への縮退」)。
65
+ 4. **config load fail-open は config mutation の許可を意味しない。** hook / doctor は missing / invalid config でも完走するが、agent hook 経由の config direct Write/Edit は ADR-041 の protected trust root として常に block する。復旧は managed command、または人間の hook 外編集で行う。 <!-- @work-item-id WI-390 -->
64
66
 
65
67
  ### 4. 既知ギャップ(本 ADR は現状を固定し、修正は別 WI)
66
68
 
@@ -76,3 +78,4 @@ config の解決順は project 直下 `phasegate.config.json` → `.phasegate-lo
76
78
  - doctor は config 状態を常に報告する(JSON: `configStatus`、human: `Config:` 行、finding: `config-status`)。config 不在・不正のまま GREEN を報告することはなくなる(missing は warn、invalid-* は red で exit 1)。
77
79
  - 許可表が仕様となったため、fail-open/fail-closed の変更は本 ADR の改訂を伴う。
78
80
  - 経緯: WI-314(hook/doctor fail-open 化)→ WI-323(hook adapter の JSON parse fail-open)→ WI-325(`ConfigParseError` 導入)→ WI-330(本 ADR・doctor 可視化・missing 系テスト固定)→ WI-333(G1 解消: hook adapter の ENOENT fail-open、github#40 完全解消)。
81
+ - WI-390 / ADR-041 で、自己修復経路を「direct agent mutation」から managed CLI / human out-of-band edit へ移し、config 自身を non-excludable protected trust root に改訂した。hook / doctor 起動と無関係操作の fail-open は維持する。
@@ -0,0 +1,68 @@
1
+ ---
2
+ adr_id: "041"
3
+ title: "agent hook の防御 trust root は config から除外不能にする"
4
+ status: Accepted
5
+ date: 2026-08-10
6
+ ---
7
+
8
+ # agent hook の防御 trust root は config から除外不能にする
9
+
10
+ <!-- @work-item-id WI-390 -->
11
+
12
+ ## Context
13
+
14
+ GitHub #50 の Grok 実機 smoke で、pre-tool-use hook は `.husky/*` 書き込みを正しく block したが、
15
+ block 文面に含まれた `phasegate.config.json protectedFiles.exclude` の手順を agent が実行し、再試行を成功させた。
16
+ 既存 `ProtectedFileList` は config 自身を既定保護せず、すべての default pattern を同じ `exclude` で削除できる。
17
+ したがって gate の authorization input を gate 対象 agent 自身が書き換えられる循環が成立する。
18
+
19
+ ADR-039 は authorization を hook が観測・検証できる state に限定したが、観測対象 config の保全境界は未定義だった。
20
+ ADR-038 は自己修復デッドロック回避のため config direct Write を全状態で fail-open としたが、その後
21
+ `install` / `init` / `setup:agent` / `config:plan --apply` という managed command が整備され、direct agent mutation を
22
+ 唯一の recovery path とする必要はなくなった。
23
+
24
+ ## Decision
25
+
26
+ ### 1. trust root patterns を config から除外不能にする
27
+
28
+ 次の path は `protectedFiles.exclude` より上位の non-excludable set とする。
29
+
30
+ - project / personal `phasegate.config.json`
31
+ - `.phasegate/baseline.json`
32
+ - `.husky/**`
33
+ - root agent instruction (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`)
34
+
35
+ 通常の formatter / compiler / package files と user additional patterns は従来どおり exclude 可能とする。
36
+
37
+ ### 2. config direct Write/Edit は config 状態を問わず block する
38
+
39
+ valid / missing / invalid-json / invalid-schema のいずれでも、agent hook 経由の config direct mutation は
40
+ path-based protected-file block とする。diff の「緩和方向」判定は採らない。before content の欠落、partial Edit、
41
+ encoding、複数 path mutation により agent-controlled diff を authorization 根拠にできないためである。
42
+
43
+ ### 3. recovery path を managed command と human out-of-band edit に分離する
44
+
45
+ - supported intent: `phasegate config:plan --intent ... --dry-run/--apply`
46
+ - bootstrap: `phasegate install|init|setup:agent ... --apply`
47
+ - invalid-schema や未対応 intent: 人間が agent hook 外で review して編集
48
+
49
+ hook / doctor 自体の config load fail-open と無関係操作の継続は ADR-038 のまま維持する。
50
+
51
+ ### 4. block message に解除レシピを出さない
52
+
53
+ stderr は managed route と documentation / human review を案内し、具体的な `protectedFiles.exclude` pattern を
54
+ 出力しない。security control の解除方法は agent-facing error contract に含めない。
55
+
56
+ ## Consequences
57
+
58
+ - agent が hook の文面を実行して同一 session 内で防御を解除する経路は閉じる。
59
+ - 既存 config が trust root を exclude していても新 version では無視される。
60
+ - agent による arbitrary config editing はできなくなる。managed intent がない変更は人間の明示操作が必要になる。
61
+ - ADR-038 の config 自身への編集行を改訂し、missing/invalid 状態の fail-open は hook 起動と無関係操作に限定する。
62
+ - Markdown を一般 docs 分類しても root agent instructions は protected 境界で先に止まる。
63
+
64
+ ## Alternatives
65
+
66
+ 1. **緩和方向の JSON diff だけ block** — partial edits と invalid config で正しく比較できず、判定不能が新たな bypass になる。
67
+ 2. **block 後に confirmation token を要求** — agent が自己申告できない observable state の設計と lifecycle が必要で、本 WI の managed command より複雑。
68
+ 3. **message だけ変更** — config 自身が writable なため agent がソースや schema から同じ bypass を発見でき、trust boundary は直らない。
@@ -0,0 +1,26 @@
1
+ # Google Antigravity CLI Integration
2
+
3
+ <!-- @work-item-id WI-385 -->
4
+
5
+ Phasegate manages a named `phasegate-gate` definition in `.agents/hooks.json`. User-owned named definitions are preserved; install and reconcile replace only the Phasegate-owned key, and uninstall removes only that key from a merged file.
6
+
7
+ Minimum supported runtime: Antigravity CLI v1.0.14, where hooks are available; Phasegate verification targets `agy` 1.1.x. If the gate appears silently inactive, open `agy`, run `/hooks`, and confirm `phasegate-gate` is loaded. Project skills are exposed through `.agents/skills`, which Phasegate links to the shared `skills/` catalog.
8
+
9
+ ## Setup
10
+
11
+ ```bash
12
+ npx phasegate install --agent antigravity --with-husky --apply
13
+ npx phasegate doctor --agent antigravity
14
+ ```
15
+
16
+ The PreToolUse regular expression covers `write_to_file`, `replace_file_content`, `multi_replace_file_content`, and `run_command`, invoking `npx phasegate hook pre-tool-use` with a 30-second timeout. Nested `toolCall.name` / `toolCall.args` payloads accept defensive path candidates (`TargetFile`, `targetFile`, `target_file`, `filePath`, `file_path`, `path`), content candidates, and command candidates (`CommandLine`, `command`, `Command`). These candidate keys are compatibility inputs, not claims that every runtime/version has been verified. Missing targets or commands fail closed.
17
+
18
+ ## Result contract
19
+
20
+ - Deny writes only documented top-level `decision: "deny"` and `reason` fields to stdout, writes the reason to stderr, and exits 2.
21
+ - Allow exits 0 with empty stdout and does not override permission.
22
+ - Workspace cwd uses `workspacePaths[0]`, falling back to the hook process cwd.
23
+
24
+ ## Supported surface and residual risk
25
+
26
+ Pre-edit hard blocking is supported for the terminal `agy` CLI surface. Antigravity IDE/desktop hook execution is not guaranteed and is not advertised as protected; L2 pre-commit is the primary defense there. The exact args keys across releases, the meaning of exit code alone, and timeout/crash failure semantics remain unverified runtime behavior. Keep L2 pre-commit and CI enabled and inspect loaded hooks with `/hooks`.
@@ -22,12 +22,12 @@ Command names in this document are split into three surfaces:
22
22
 
23
23
  | Command | Description |
24
24
  |---|---|
25
- | `init --name <name>` | Legacy-compatible bootstrap for new projects: deploy skills, generate config, and optionally add hooks/CI. Options: `--preset <full\|standard\|minimal\|custom>`, `--skills <core\|all>`, `--agent <claude\|codex\|both>`, `--workflow <standard\|strict>`, `--language <language>`, `--with-husky`, `--with-ci`, `--yes`. `--language` writes `project.languages: ["<language>"]`; omitted language keeps the TypeScript-compatible default. <!-- @work-item-id WI-212 --> |
26
- | `install --dry-run` / `--apply` | Idempotently merge PhaseGate into an existing project, preserve user content, add package scripts/devDependency, create selected `AGENTS.md` / `CLAUDE.md` managed sections, and write `.phasegate/manifest.json`. `--agent <claude\|codex\|both>`, `--skills <core\|all>`, and `--workflow <standard\|strict>` affect rendered agent context; `--force` replaces managed targets after backup. |
27
- | `doctor` | Diagnose silent or partial installations and report repair hints (`--json`, `--strict`, `--agent <claude\|codex\|both>`, `--report-out <path>`). `--agent` defaults to `both`; single-agent scopes keep shared targets applicable and mark the other agent's findings as not applicable. `--report-out` writes exactly to the supplied path, not to `reporting.outputDir`. |
25
+ | `init --name <name>` | Legacy-compatible bootstrap for new projects: deploy skills, generate config, and optionally add hooks/CI. Options: `--preset <full\|standard\|minimal\|custom>`, `--skills <core\|all>`, `--agent <claude\|codex\|both\|grok\|antigravity\|all>`, `--workflow <standard\|strict>`, `--language <language>`, `--with-husky`, `--with-ci`, `--yes`. `--language` writes `project.languages: ["<language>"]`; omitted language keeps the TypeScript-compatible default. <!-- @work-item-id WI-212, WI-385 --> |
26
+ | `install --dry-run` / `--apply` | Idempotently merge PhaseGate into an existing project, preserve user content, add package scripts/devDependency, create selected context/hooks, and write `.phasegate/manifest.json`. `--agent <claude\|codex\|both\|grok\|antigravity\|all>` selects runtime targets; `both` remains Claude + Codex and `all` selects every supported runtime. `--force` replaces managed targets after backup. <!-- @work-item-id WI-385 --> |
27
+ | `doctor` | Diagnose silent or partial installations and report repair hints (`--json`, `--strict`, `--agent <claude\|codex\|both\|grok\|antigravity\|all>`, `--report-out <path>`). Grok scope checks compatible matcher/timeout and emits trust guidance; Antigravity scope checks named schema/matcher/timeout and emits the CLI-only boundary. <!-- @work-item-id WI-385 --> |
28
28
  | `uninstall --dry-run` / `--apply` | Remove PhaseGate-managed files and managed blocks using `.phasegate/manifest.json`; `--force` handles managed conflict cases. |
29
29
  | `reconcile --dry-run` / `--apply` | Update PhaseGate-managed files to current package templates and refresh manifest hashes; `--force` allows managed-file replacement with backup. |
30
- | `setup:agent` | Agent-readable setup planner and optional apply path. Options: `--intent <minimal\|recommended\|strict\|ci-only\|agent-hooks\|retrofit>`, `--agent <claude\|codex\|both>`, `--workflow <standard\|strict>`, `--with-husky`, `--with-ci`, `--dry-run`, `--apply`, `--json`. <!-- @work-item-id WI-172 --> |
30
+ | `setup:agent` | Agent-readable setup planner and optional apply path. Options: `--intent <minimal\|recommended\|strict\|ci-only\|agent-hooks\|retrofit>`, `--agent <claude\|codex\|both\|grok\|antigravity\|all>`, `--workflow <standard\|strict>`, `--with-husky`, `--with-ci`, `--dry-run`, `--apply`, `--json`. <!-- @work-item-id WI-172, WI-385 --> |
31
31
  | `config:plan` | Agent-readable configuration change planner. Options: `--intent <l4-strict\|codex-hooks\|ci-fail-on-warning\|baseline-reset\|quick-mode-strict\|quick-mode-relax\|retrofit-bootstrap\|planning-mode-relax>`, `--dry-run`, `--apply`, `--json`. <!-- @work-item-id WI-173 --> <!-- @work-item-id WI-201 --> <!-- @work-item-id WI-204 --> |
32
32
  | `session begin` / `session end` | Hook-visible Full Mode session manager. Use `session begin --mode full --unit <unit> --work-item <WI-XXX> --reason <text> --duration <ttl>` before implementation that must touch Quick Mode disallowed categories, and `session end --work-item <WI-XXX>` after completion. <!-- @work-item-id WI-206 --> |
33
33
  | `update-skills` | Compatibility alias for `reconcile`; use `reconcile` for new automation. |
@@ -1,56 +1,32 @@
1
1
  # Codex CLI Integration
2
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.
3
+ <!-- @work-item-id WI-384 -->
4
+
5
+ Phasegate supports OpenAI Codex CLI through project-local command hooks. Codex rust-v0.124.0 or newer is required for native `apply_patch` coverage; hooks are stable and enabled by default in those releases.
4
6
 
5
7
  ## Setup
6
8
 
7
- ### Quick setup (recommended)
9
+ Install or reconcile the managed Codex artifacts:
8
10
 
9
11
  ```bash
10
- # 1. Initialize the project for Codex
11
- npx phasegate init --name my-project --agent codex --with-husky
12
-
13
- # 2. Enable the Codex CLI feature flag manually
14
- codex features enable hooks
15
- ```
16
-
17
- For dual-agent projects (Claude + Codex), use `--agent both`.
18
-
19
- Responsibility split:
20
-
21
- - `phasegate init --agent codex` sets up **project-local artifacts** such as `phasegate.config.json`, `skills/`, `.codex/hooks.json`, and `.codex/skills`
22
- - `codex features enable hooks` updates the **Codex CLI user environment** and is intentionally left as a manual step
23
-
24
- ### Manual setup
25
-
26
- Alternatively, set up Codex integration manually:
27
-
28
- #### 1. Enable hooks in Codex config
29
-
30
- Add to `~/.codex/config.toml` (or project `.codex/config.toml`):
31
-
32
- ```toml
33
- [features]
34
- hooks = true
12
+ npx phasegate install --agent codex --with-husky --apply
13
+ npx phasegate doctor --agent codex
35
14
  ```
36
15
 
37
- #### 2. Install Phasegate hooks
16
+ Use `--agent both` for projects shared with Claude Code. After `.codex/hooks.json` is created or changed, open `/hooks` in Codex and trust the current hook definition hash. Trust is stored outside the project and cannot be verified by Phasegate, so install, reconcile, and doctor print an operator notice.
38
17
 
39
- Copy the template into your project:
18
+ The deprecated `phasegate init --agent codex` path remains available and prints the same minimum-version and re-trust guidance.
40
19
 
41
- ```bash
42
- mkdir -p .codex
43
- cp node_modules/phasegate/templates/.codex/hooks.json .codex/hooks.json
44
- ```
20
+ ### Manual configuration
45
21
 
46
- Or merge the following into your existing `.codex/hooks.json`:
22
+ The canonical matcher is `Bash|apply_patch` for both events:
47
23
 
48
24
  ```json
49
25
  {
50
26
  "hooks": {
51
27
  "PreToolUse": [
52
28
  {
53
- "matcher": "Bash",
29
+ "matcher": "Bash|apply_patch",
54
30
  "hooks": [
55
31
  {
56
32
  "type": "command",
@@ -62,7 +38,7 @@ Or merge the following into your existing `.codex/hooks.json`:
62
38
  ],
63
39
  "PostToolUse": [
64
40
  {
65
- "matcher": "Bash",
41
+ "matcher": "Bash|apply_patch",
66
42
  "hooks": [
67
43
  {
68
44
  "type": "command",
@@ -71,97 +47,58 @@ Or merge the following into your existing `.codex/hooks.json`:
71
47
  }
72
48
  ]
73
49
  }
74
- ],
75
- "Stop": [
76
- {
77
- "hooks": [
78
- {
79
- "type": "command",
80
- "command": "npx phasegate hook stop",
81
- "statusMessage": "phasegate: completion check",
82
- "timeout": 30
83
- }
84
- ]
85
- }
86
50
  ]
87
51
  }
88
52
  }
89
53
  ```
90
54
 
91
- #### 3. Enable the pre-commit hook (critical for Codex)
92
-
93
- 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:
94
-
95
- ```bash
96
- npx phasegate init --with-husky # or rerun init with this flag
97
- ```
98
-
99
- ## Defense Layers in Codex
100
-
101
- Compared to Claude Code, the enforcement timing is shifted for `apply_patch`-based edits. Coverage is equivalent overall but arrives at different stages.
55
+ `Write` and `Edit` aliases are not included in the Codex-specific template. `apply_patch` is the canonical upstream tool name.
102
56
 
103
- | Concern | Claude Code | Codex |
104
- |---|---|---|
105
- | Bash-based file writes (`sed -i`, `tee`, heredoc) | `PreToolUse(Bash)` — hard block | `PreToolUse(Bash)` — hard block (same) |
106
- | Bash-invoked `apply_patch <<'PATCH'` | `PreToolUse(Bash)` — hard block | `PreToolUse(Bash)` — hard block (via Wave 1 `apply_patch` heredoc detection) |
107
- | **Native `apply_patch` tool calls** | `PreToolUse(Write\|Edit)` — hard block | ⚠️ **Not intercepted by hooks** — deferred to pre-commit |
108
- | Protected file writes | hook — immediate block | hook (Bash path) + pre-commit (commit path) |
109
- | Phase-gate enforcement | hook — immediate block | hook (Bash path) + pre-commit (commit path) |
110
- | Post-edit formatter / lint | `PostToolUse(Write\|Edit)` | `PostToolUse(Bash)` (partial) |
111
- | Session completion check | `Stop` hook | `Stop` hook (same) |
57
+ ## Coverage
112
58
 
113
- ## Known Limitations
59
+ | Edit path | Pre-edit hard block | Post-edit lint | Commit-time backstop |
60
+ |---|---|---|---|
61
+ | Shell writes (`sed -i`, `tee`, heredoc, `cat >`) | ✅ `PreToolUse(Bash)` | ✅ `PostToolUse(Bash)` | ✅ L2 pre-commit |
62
+ | Bash-invoked `apply_patch <<'PATCH'` | ✅ parsed by `BashWriteTargetExtractor` | ✅ `PostToolUse(Bash)` | ✅ L2 pre-commit |
63
+ | Native `apply_patch` Update/Add/Delete/Move to | ✅ `PreToolUse(apply_patch)` | ✅ `PostToolUse(apply_patch)` | ✅ L2 pre-commit |
114
64
 
115
- ### Native `apply_patch` bypasses hooks
65
+ For native patches, Phasegate reads raw patch text from `tool_input.command`, preserves directive order, and maps Update/Add/Delete to MODIFY/CREATE/DELETE. An Update followed by `*** Move to:` adds the source as MODIFY and the destination as CREATE. All targets join the existing protected-file, phase-gate, story-reflection, and Quick/Full Mode checks. One violating target denies the whole patch before editing.
116
66
 
117
- Per [OpenAI Codex docs](https://developers.openai.com/codex/hooks):
67
+ PostToolUse intentionally does not parse patch targets again. It sends the event through the existing fast lint path.
118
68
 
119
- > "Currently `PreToolUse` only supports Bash tool interception."
69
+ ## Hook result contract
120
70
 
121
- 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:
71
+ - Deny: exit 2 with non-empty stderr.
72
+ - Continue: exit 0 with empty stdout. Informational stderr is allowed.
73
+ - Phasegate does not emit `permissionDecision: "ask"` because that path can fail open.
74
+ - Phasegate does not emit an `allow` response without `updatedInput`.
75
+ - Missing `tool_input.command` or a patch without `*** Begin Patch` fails closed.
122
76
 
123
- - Phasegate cannot pre-block edits made through native `apply_patch`
124
- - Violations surface at **pre-commit time** instead
125
- - Feedback is delayed relative to the Claude Code experience
77
+ ## Layered defense and residual risk
126
78
 
127
- **Mitigation**: commit frequently (e.g., after each logical unit of work). This shortens the window between violation and detection.
79
+ Command hooks are a fast path. They can be skipped until the updated definition is trusted, and project code cannot inspect Codex's external trust store. Keep `.husky/pre-commit` and CI enabled: L2 remains the commit-time backstop and CI remains the authoritative re-check.
128
80
 
129
- ### Bash-invoked `apply_patch` is fully covered
81
+ Codex CLI 0.144.5 still exposes `unified_exec`, whose interception coverage is incomplete. Commands routed through an unobserved `unified_exec` path may bypass the edit-time hook; L2 pre-commit and CI remain the fallback for that residual risk.
130
82
 
131
- 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.
132
-
133
- ### Windows is not supported
134
-
135
- Codex hooks themselves do not support Windows. Phasegate follows the same constraint.
136
-
137
- ### `unified_exec` interception is incomplete
138
-
139
- 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.
140
-
141
- ## Recommended Workflow
142
-
143
- 1. **Enable all three layers**: Codex hooks + pre-commit hook + CI validation
144
- 2. **Commit frequently** to catch native apply_patch violations early
145
- 3. **Review the coverage matrix** above so you understand which edits are hard-blocked vs caught later
83
+ Windows Codex hooks and Codex versions older than 0.124.0 are not supported by this integration.
146
84
 
147
85
  ## Troubleshooting
148
86
 
149
- ### Hooks don't seem to run
150
-
151
- - Verify `hooks = true` is set in `config.toml`
152
- - Verify `.codex/hooks.json` is in the project root or `~/.codex/`
153
- - Run `codex --version` to ensure you're on a version that supports hooks
154
-
155
- ### False positives on Bash hooks
87
+ ### Native apply_patch is not intercepted
156
88
 
157
- 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.
89
+ 1. Run `codex --version` and confirm 0.124.0 or newer.
90
+ 2. Confirm both matchers in `.codex/hooks.json` are `Bash|apply_patch`.
91
+ 3. Run `npx phasegate doctor --agent codex`.
92
+ 4. Run `npx phasegate reconcile --apply` if doctor reports stale wiring.
93
+ 5. Open `/hooks` and trust the current definition hash.
158
94
 
159
- ### Native apply_patch violations slipped through
95
+ ### A patch is denied
160
96
 
161
- 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`.
97
+ Read stderr for the blocked path and recovery guidance. Full Mode changes require an active `phasegate session begin --mode full ...` authorization. Malformed or target-less native patches are denied rather than silently allowed.
162
98
 
163
- ## See Also
99
+ ## See also
164
100
 
165
- - [Claude Code Hooks Integration](./hooks-integration.md)
166
- - [Phasegate Layer Model](./layer-model.md)
167
- - [Codex Hooks Documentation (official)](https://developers.openai.com/codex/hooks)
101
+ - [Hooks Integration](./hooks-integration.md)
102
+ - [Layer Model](./layer-model.md)
103
+ - [OpenAI Codex hooks documentation](https://developers.openai.com/codex/hooks)
104
+ - [openai/codex PR #18391](https://github.com/openai/codex/pull/18391)