phasegate 0.315.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.
- package/CHANGELOG.md +4 -0
- package/README.ja.md +22 -9
- package/README.md +28 -17
- package/docs/ADR/038-config-state-operation-permission-policy.md +5 -2
- package/docs/ADR/039-hook-observable-state-as-authorization-unit.md +74 -0
- package/docs/ADR/040-quick-mode-config-via-preset-resolution.md +66 -0
- package/docs/ADR/041-non-excludable-agent-trust-roots.md +68 -0
- package/docs/guide/antigravity-integration.md +26 -0
- package/docs/guide/cli-reference.md +93 -11
- package/docs/guide/codex-integration.md +44 -107
- package/docs/guide/configuration.md +43 -2
- package/docs/guide/grok-integration.md +26 -0
- package/docs/guide/hooks-integration.md +27 -4
- package/docs/guide/installation.md +4 -2
- package/docs/guide/quick-vs-full-mode.md +36 -1
- package/docs/guide/setup-artifacts.md +4 -4
- package/docs/guide/skills-overview.md +1 -1
- package/package.json +2 -2
- package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +6 -2
- package/scripts/harness/agent-integration/application/dto/normalized-pre-tool-use-request.ts +32 -0
- package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +17 -9
- package/scripts/harness/agent-integration/domain/ports/full-mode-requirement-query-port.ts +3 -1
- package/scripts/harness/agent-integration/domain/services/apply-patch-write-target-extractor.ts +98 -0
- package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +196 -54
- package/scripts/harness/agent-integration/domain/value-objects/hook-translation-result.ts +1 -1
- package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +39 -17
- package/scripts/harness/agent-integration/infrastructure/adapters/quick-mode-full-mode-requirement-adapter.ts +15 -1
- package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +1 -1
- package/scripts/harness/agent-integration/presentation/post-tool-use-hook.ts +1 -0
- package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +129 -73
- package/scripts/harness/agent-integration/presentation/pre-tool-use-payload-normalizer.ts +228 -0
- package/scripts/harness/agent-integration/presentation/pre-tool-use-response-renderer.ts +38 -0
- package/scripts/harness/ci-governance/application/dto/scaffold-inception-input.ts +9 -0
- package/scripts/harness/ci-governance/application/dto/scaffold-inception-output.ts +13 -0
- package/scripts/harness/ci-governance/application/usecases/list-templates-usecase.ts +30 -0
- package/scripts/harness/ci-governance/application/usecases/scaffold-inception-usecase.ts +63 -0
- package/scripts/harness/ci-governance/application/usecases/show-template-usecase.ts +39 -0
- package/scripts/harness/ci-governance/composition-root.ts +55 -3
- package/scripts/harness/ci-governance/domain/ports/inception-doc-writer-port.ts +19 -0
- package/scripts/harness/ci-governance/domain/ports/inception-template-repository-port.ts +16 -0
- package/scripts/harness/ci-governance/domain/ports/template-catalog-port.ts +23 -0
- package/scripts/harness/ci-governance/domain/value-objects/inception-doc-kind.ts +109 -0
- package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +2 -0
- package/scripts/harness/ci-governance/domain/value-objects/template-catalog-entry.ts +53 -0
- package/scripts/harness/ci-governance/domain/value-objects/template-name.ts +50 -0
- package/scripts/harness/ci-governance/infrastructure/adapters/file-system-inception-doc-writer-adapter.ts +42 -0
- package/scripts/harness/ci-governance/infrastructure/adapters/file-system-inception-template-repository-adapter.ts +32 -0
- package/scripts/harness/ci-governance/infrastructure/adapters/file-system-template-catalog-adapter.ts +60 -0
- package/scripts/harness/ci-governance/presentation/handlers/scaffold-inception-handler.ts +101 -0
- package/scripts/harness/ci-governance/presentation/handlers/templates-handler.ts +103 -0
- package/scripts/harness/config-foundation/domain/harness-config.ts +12 -0
- package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +2 -2
- package/scripts/harness/config-foundation/infrastructure/presets/standard.json +2 -2
- package/scripts/harness/config-foundation/infrastructure/presets/strict.json +2 -2
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +44 -1
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +42 -1
- package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +3 -1
- package/scripts/harness/installation/application/checks/antigravity-hook-missing-check.ts +79 -0
- package/scripts/harness/installation/application/checks/codex-hook-missing-check.ts +70 -6
- package/scripts/harness/installation/application/checks/grok-hook-missing-check.ts +79 -0
- package/scripts/harness/installation/application/checks/husky-runtime-inactive-check.ts +33 -0
- package/scripts/harness/installation/application/named-hook-json.ts +17 -0
- package/scripts/harness/installation/application/operator-notice.ts +42 -0
- package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +18 -7
- package/scripts/harness/installation/application/usecases/run-install.ts +152 -52
- package/scripts/harness/installation/application/usecases/run-reconcile.ts +86 -10
- package/scripts/harness/installation/application/usecases/run-uninstall.ts +149 -25
- package/scripts/harness/installation/composition-root.ts +10 -0
- package/scripts/harness/installation/domain/agent-target.ts +39 -0
- package/scripts/harness/installation/domain/check-id.ts +5 -0
- package/scripts/harness/installation/domain/husky-runtime-state.ts +34 -0
- package/scripts/harness/installation/domain/ports/git-hooks-runtime-probe.ts +9 -0
- package/scripts/harness/installation/domain/repair-table.ts +5 -0
- package/scripts/harness/installation/infrastructure/adapters/git-hooks-runtime-probe-adapter.ts +62 -0
- package/scripts/harness/installation/presentation/cli/install-handler.ts +23 -4
- package/scripts/harness/installation/presentation/cli/reconcile-handler.ts +7 -1
- package/scripts/harness/installation/presentation/formatters/diagnostic-report-formatter.ts +27 -0
- package/scripts/harness/main.ts +202 -51
- package/scripts/harness/phase-dependency-model/application/services/evidence-bundle-assembler.ts +2 -1
- package/scripts/harness/phase-dependency-model/domain/ports/plan-document-reader-port.ts +12 -0
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/markdown-plan-document-reader.ts +4 -1
- package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +1 -1
- package/scripts/harness/quick-mode/application/dto/quick-mode-eligibility-contract.ts +1 -1
- package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +3 -1
- package/scripts/harness/quick-mode/domain/errors/quick-mode-config-error.ts +19 -0
- package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +59 -19
- package/scripts/harness/quick-mode/domain/types/rejection-rule.ts +1 -1
- package/scripts/harness/quick-mode/domain/value-objects/category-override-rules.ts +147 -0
- package/scripts/harness/quick-mode/domain/value-objects/change-category.ts +33 -0
- package/scripts/harness/quick-mode/domain/value-objects/quick-mode-config.ts +31 -10
- package/scripts/harness/quick-mode/index.ts +7 -1
- package/scripts/harness/quick-mode/infrastructure/adapters/harness-config-quick-mode-config-adapter.ts +83 -32
- package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +13 -3
- package/skills/product-architect/SKILL.md +19 -0
- package/skills/story-mapper/SKILL.md +11 -0
- package/skills/story-writer/SKILL.md +11 -0
- package/skills/unit-designer/SKILL.md +11 -0
- package/templates/.agents/hooks.json +16 -0
- package/templates/.claude/scripts/analyze-errors-hook.sh +2 -2
- package/templates/.claude/settings.json +5 -3
- package/templates/.codex/hooks.json +2 -2
- package/templates/product_overview.template.md +85 -0
- package/templates/product_overview_plan.template.md +55 -0
- package/templates/story_mapping_plan.template.md +61 -0
- package/templates/story_writer_plan.template.md +61 -0
- package/templates/unit_design_plan.template.md +63 -0
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
|
|
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
|
|
163
|
-
|
|
162
|
+
npx phasegate install --agent codex --with-husky --apply
|
|
163
|
+
npx phasegate doctor --agent codex
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
両方使う場合は `--agent both`。Codex
|
|
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
|
|
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
|
-
`
|
|
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` |
|
|
482
|
+
| Codex ネイティブ `apply_patch` Update/Add/Delete | ✅ PreToolUse(apply_patch) | ✅ pre-commit |
|
|
472
483
|
|
|
473
|
-
|
|
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
|
|
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
|
|
147
|
-
|
|
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
|
|
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
|
-
| **
|
|
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
|
|
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.
|
|
555
|
-
npx phasegate
|
|
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.
|
|
558
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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`
|
|
582
|
+
| Native `apply_patch` Update/Add/Delete | ✅ `PreToolUse(apply_patch)` | ✅ pre-commit |
|
|
574
583
|
|
|
575
|
-
|
|
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) |
|
|
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
|
|
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,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
adr_id: "039"
|
|
3
|
+
title: "hook の authorization 単位は観測可能な state とし、skill 名を伝播しない"
|
|
4
|
+
status: Accepted
|
|
5
|
+
date: 2026-08-06
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# hook の authorization 単位は観測可能な state とし、skill 名を伝播しない
|
|
9
|
+
|
|
10
|
+
<!-- @work-item-id WI-375 -->
|
|
11
|
+
<!-- @work-item-id WI-376 -->
|
|
12
|
+
|
|
13
|
+
## Context
|
|
14
|
+
|
|
15
|
+
pre-tool-use hook には「呼び出し元 skill 名」を受け取る口が 2 つ実装されていた。
|
|
16
|
+
|
|
17
|
+
- hook input JSON の `caller_skill` フィールド(`scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts` の `PreToolUseHookInput`)
|
|
18
|
+
- 環境変数 `PHASEGATE_CALLER_SKILL`(同ファイルの `input.caller_skill ?? process.env.PHASEGATE_CALLER_SKILL`)
|
|
19
|
+
|
|
20
|
+
WI-202 はこれを「block guidance の出し分けにのみ使う optional context」として設計した。しかし **値を供給する producer はどこにも存在しない**。
|
|
21
|
+
|
|
22
|
+
1. **Claude Code の PreToolUse payload に skill 情報が無い。** hook に渡る JSON は `session_id` / `transcript_path` / `cwd` / `hook_event_name` / `tool_name` / `tool_input` / `permission_mode` であり、実行中の skill を示すフィールドは規定されていない。`caller_skill` は phasegate が独自に期待しているだけの未定義キーである。
|
|
23
|
+
2. **配布物の `.claude/settings.json` にも `.codex/hooks.json` にも `PHASEGATE_CALLER_SKILL` を設定する env 宣言が無い。** skill 側(`skills/*/SKILL.md`)にも export する手順は書かれていない。
|
|
24
|
+
3. 結果として `callerSkill` は常に `undefined` で hook に届き、`callerSkill === "quick-implementor"` の分岐は **到達不能なデッドパス**だった。それでも `HandlePreToolUseUseCase` を直接 new して `callerSkill: "quick-implementor"` を渡す統合テストは緑になっており、「実運用では一度も通らない経路が、テスト上は被覆されている」という**偽の被覆**を生んでいた(GitHub #27 Defect C / #44 課題 1)。
|
|
25
|
+
|
|
26
|
+
WI-354 で guidance 分岐の一次条件を `dominantCategory`(Quick Mode の分類結果)に変更したため実害は解消済みだが、「カテゴリ未確定時のみ `callerSkill` を見る」フォールバックと受け口自体は残っていた。
|
|
27
|
+
|
|
28
|
+
さらに本質的な問題として、**skill 名は仮に producer を作っても認証されない自己申告値である**。hook を呼ぶのはエージェント自身であり、`caller_skill: "quick-implementor"` を名乗ることは誰にでもできる。ADR-030(injection threat model)の trust root の考え方に照らせば、エージェントが自由に制御できる文字列は防御判定の入力にできない。GitHub #26 で「skill 名で full mode を許可する」案を退け、`phasegate config:plan --apply` のような **managed command 経路**(phasegate 自身が実行し、その痕跡をファイルとして残す経路)に倒した結論と同根である。
|
|
29
|
+
|
|
30
|
+
## Decision
|
|
31
|
+
|
|
32
|
+
### 1. authorization / guidance の入力は「hook が自ら観測・検証できる state」に限る
|
|
33
|
+
|
|
34
|
+
pre-tool-use hook の判定と案内は、以下の観測可能な state のみを入力とする。
|
|
35
|
+
|
|
36
|
+
| state | 実体 | 観測方法 |
|
|
37
|
+
|-------|------|---------|
|
|
38
|
+
| 書き込み対象パスと変更カテゴリ | `tool_input` から抽出した対象パス、Quick Mode の `dominantCategory` | hook 自身が分類(`quick-mode` unit) |
|
|
39
|
+
| Full Mode session marker | `phasegate session begin --mode full --unit … --work-item …` が作るセッションファイル(WI / unit / 期限) | `FileSystemFullModeSessionQueryAdapter` がファイルを読む |
|
|
40
|
+
| 設計文書の存在 | `docs/product/construction/{unit}/logical_design.md` / `domain_model.md` | `PhaseGateQueryAdapter.checkDesignDocsExist` |
|
|
41
|
+
| WI の承認・reflection 状態 | inception 配下の WI 文書、story reflection | 各 query adapter がファイルを読む |
|
|
42
|
+
| 解決済み config | `phasegate.config.json` + 防御プリセット解決結果 | config-foundation 経由 |
|
|
43
|
+
| baseline / attestation | `.phasegate/baseline.json`、attestation マニフェスト | ci-governance / attestation unit |
|
|
44
|
+
|
|
45
|
+
これらはすべて「phasegate 自身の managed command が書いた痕跡」または「リポジトリの実ファイル」であり、hook 実行時点で独立に再検証できる。
|
|
46
|
+
|
|
47
|
+
### 2. エージェントの自己申告 identity は受け取らない
|
|
48
|
+
|
|
49
|
+
skill 名・エージェント種別のような自己申告値は、**authorization にも guidance 分岐にも使わない**。よって受け口を削除する。
|
|
50
|
+
|
|
51
|
+
- `PreToolUseHookInput.caller_skill` フィールドを削除する
|
|
52
|
+
- 環境変数 `PHASEGATE_CALLER_SKILL` の参照を削除する
|
|
53
|
+
- `HandlePreToolUseInput.callerSkill` を削除する
|
|
54
|
+
- `shouldGuideQuickModeRelax` の `callerSkill === "quick-implementor"` フォールバックを削除する(判定は `dominantCategory` のみ)
|
|
55
|
+
- `callerSkill` を注入するだけで成立していた統合テストを削除し、代わりに **category ベースの分岐が WI-354 の挙動のまま不変であること**を回帰テストで固定する
|
|
56
|
+
|
|
57
|
+
「使われていない口を念のため残す」ことは、偽の被覆を生み、将来「値さえ入れれば許可が広がる」という誤った拡張余地を残すため採らない。
|
|
58
|
+
|
|
59
|
+
### 3. skill context が必要になった場合の唯一の入口は managed command
|
|
60
|
+
|
|
61
|
+
将来「どの skill が書いているか」に応じて挙動を変える必要が生じた場合も、hook input に新しい自己申告フィールドを足すことはしない。skill 側に `phasegate session begin` 等の **managed command を実行させ、その結果として生まれた検証可能な state**(session marker のフィールド)を hook が読む方式のみを採る。この経路では phasegate が引数を検証し、期限・unit・WI を自ら記録するため、値の出所が hook から追跡できる。
|
|
62
|
+
|
|
63
|
+
## Consequences
|
|
64
|
+
|
|
65
|
+
- pre-tool-use hook の入力契約から `caller_skill` が消える。未定義キーを送っていた呼び出し元があっても、hook は追加キーを無視するため互換性は壊れない(そもそも producer が存在しない)。
|
|
66
|
+
- Full Mode ブロック時の復旧案内は `dominantCategory` のみから決まる。`bugfix` / `docs` / `test` / `config` は quick-mode-relax 案内、`feature` / `domain` / `api` および**カテゴリ未確定**は `/story-implementor` 案内という WI-354 の挙動が唯一の仕様となる(カテゴリ未確定時に skill 名で分岐が変わる可能性が消える)。
|
|
67
|
+
- 「テストは緑だが実運用では到達しない」経路が 1 件減る。今後 hook の分岐を追加する際は、入力が上表の observable state に由来するかを ADR の基準として確認する。
|
|
68
|
+
- 経緯: WI-202(受け口の追加)→ WI-206(skill 名を許可条件にしない方針の調査)→ #26(managed command 経路への結論)→ WI-354(guidance の category ベース化)→ 本 ADR(受け口の削除と原則の明文化)。
|
|
69
|
+
|
|
70
|
+
## Alternatives
|
|
71
|
+
|
|
72
|
+
1. **producer を実装する(`.claude/settings.json` の env に `PHASEGATE_CALLER_SKILL` を埋める / skill 側で export させる)。** 値はエージェントが自由に設定できる自己申告であり、authorization の入力としては防御にならない。guidance 専用に限定しても、配布物の env 設定はユーザーの settings 編集に依存し、欠落時に静かに分岐が消えるため、category ベース判定より劣る。
|
|
73
|
+
2. **現状維持(受け口を残したまま到達不能分岐を放置)。** デッドパスと偽の被覆が残り、`callerSkill` を「渡せば許可が変わるフック」と誤解した拡張を招く。
|
|
74
|
+
3. **Claude Code 側の payload 拡張を待つ。** phasegate は AI 非依存(ADR-006)を掲げており、特定エージェントの payload 拡張に防御設計を依存させない。
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
adr_id: "040"
|
|
3
|
+
title: "Quick Mode の実効設定を防御プリセット解決経由で決定する"
|
|
4
|
+
status: Accepted
|
|
5
|
+
date: 2026-08-06
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Quick Mode の実効設定を防御プリセット解決経由で決定する
|
|
9
|
+
|
|
10
|
+
<!-- @work-item-id WI-375 -->
|
|
11
|
+
<!-- @work-item-id WI-377 -->
|
|
12
|
+
<!-- @work-item-id WI-378 -->
|
|
13
|
+
|
|
14
|
+
## Context
|
|
15
|
+
|
|
16
|
+
ADR-007 は `phasegate.config.json` を品質設定の Single Source of Truth と定め、防御プリセット(`minimal` / `standard` / `strict`)の解決は config-foundation の `PresetResolutionService` + `PresetDefinitionStore` が担う。ところが Quick Mode の実効経路である `HarnessConfigQuickModeConfigAdapter`(`scripts/harness/quick-mode/infrastructure/adapters/harness-config-quick-mode-config-adapter.ts`)は、**`phasegate.config.json` を `fs.readFile` + `JSON.parse` で直接読み、preset 解決を経由していなかった**。
|
|
17
|
+
|
|
18
|
+
その結果:
|
|
19
|
+
|
|
20
|
+
- `scripts/harness/config-foundation/infrastructure/presets/*.json` の `quickMode` セクションは**どこからも読まれないデッド宣言**だった。
|
|
21
|
+
- 実効既定値は adapter 内のハードコード定数 `DEFAULT_QUICK_MODE_CONFIG` にあり、宣言(presets)と実効値(adapter)が二重管理されていた。
|
|
22
|
+
- WI-353 で `allowedCategories` の乖離(presets が `["bugfix"]`、実効値が 4 カテゴリ)を是正し契約テストで再発を検知できるようにしたが、`maintainedLayers` / `relaxedGates` は依然乖離していた(presets: `["L1","L2"]` / `[]`、実効値かつ `docs/guide/configuration.md` の記載: `["L1","L2-002","L2-003","L2-014","L3-001"]` / `["L2-001","L3-002","L3-003","L3-004","L4"]`)。
|
|
23
|
+
- 「防御プリセットごとに Quick Mode の強度を変える」(例: `strict` では `allowedCategories` を絞る)という設計は、経路が繋がっていないため実現不能だった。
|
|
24
|
+
|
|
25
|
+
GitHub #44 課題 2。**既存プロジェクトの実効挙動を変えない移行**が絶対条件である(#27 の再発防止)。
|
|
26
|
+
|
|
27
|
+
## Decision
|
|
28
|
+
|
|
29
|
+
### 1. Quick Mode 設定は preset 解決結果(resolved config)から決定する
|
|
30
|
+
|
|
31
|
+
`HarnessConfigQuickModeConfigAdapter` は `PresetDefinitionStore` + `PresetResolutionService` を使い、`project.preset` に対応する preset 定義と `phasegate.config.json` の `quickMode` を config-foundation と同一の merge 規則(`deepMerge`: 配列はキー単位で全置換、未宣言キーは preset 値を継承)で解決した結果を使う。
|
|
32
|
+
|
|
33
|
+
これにより presets の `quickMode` 宣言が実際に読まれ、防御プリセットごとに Quick Mode 強度を変える設計が有効化される。
|
|
34
|
+
|
|
35
|
+
### 2. 移行時は挙動不変を絶対条件とし、presets の宣言値を実効既定値に揃える
|
|
36
|
+
|
|
37
|
+
経路の載せ替えだけを行うと、`quickMode` を書いていない既存プロジェクトの `maintainedLayers` / `relaxedGates` が preset の宣言値(`["L1","L2"]` / `[]`)に変わってしまう。これは「Quick Mode で L2-001 phase-gate が維持され、L3-001 が維持されなくなる」という実挙動の変化であり、許容しない。
|
|
38
|
+
|
|
39
|
+
したがって **3 プリセットの `quickMode` 宣言を実効既定値(= `docs/guide/configuration.md` が既定として記載している値)に揃える**。WI-353 が `allowedCategories` に対して行った是正を、`maintainedLayers` / `relaxedGates` にも適用する形になる。逆方向(実効値を preset 宣言に合わせる)は既存利用者への破壊的変更であり採らない。
|
|
40
|
+
|
|
41
|
+
防御プリセットごとの Quick Mode 強度差(`strict` で絞る等)は**本 ADR では導入しない**。経路を繋ぐ変更と挙動を変える変更を同一コミットに混ぜないためである。今後差をつける場合は presets の該当ファイルのみを変更すれば実効値に反映される。
|
|
42
|
+
|
|
43
|
+
### 3. 解決不能時は従来どおりの既定値に fail-open する
|
|
44
|
+
|
|
45
|
+
`project.preset` が未知・未宣言、または preset 解決が例外を投げる config(他セクションが壊れている等)では、従来と同じく adapter 内の既定値 + raw `quickMode` の per-key フォールバックで動作する。ADR-038 §3-1 の「hook は config がどんな状態でも完走する」原則を維持し、preset 解決の導入によって**新たな遮断経路を作らない**。
|
|
46
|
+
|
|
47
|
+
`HarnessConfigNotFoundError`(ENOENT)と `HarnessConfigParseError`(JSON 不正)は adapter の公開契約として維持する。
|
|
48
|
+
|
|
49
|
+
### 4. WI-353 の契約テストは「宣言が実際に読まれること」の検証に昇格させる
|
|
50
|
+
|
|
51
|
+
WI-353 のテストは「preset 宣言値 == adapter のハードコード既定値」という**二重管理の整合**を検査していた。経路が繋がった後は、`quickMode` を持たない config に対する adapter の実効値が preset 宣言値そのものであることを 3 プリセット分検証する形に置き換える。これによりデッド宣言の解消自体が回帰テストで固定される。
|
|
52
|
+
|
|
53
|
+
あわせて「防御プリセット × `quickMode` キー有無 × 明示 override 有無」のマトリクス回帰テストで挙動不変を固定する。
|
|
54
|
+
|
|
55
|
+
## Consequences
|
|
56
|
+
|
|
57
|
+
- presets の `quickMode` が実効値の所在(single source)になり、adapter 内の既定値は preset 解決不能時の fail-open 用フォールバックという位置づけに縮小する。
|
|
58
|
+
- `phasegate` が出力する解決済み config の `quickMode` と、Quick Mode 判定が実際に使う値が一致する(従来は前者だけが preset 由来で、後者と食い違っていた)。
|
|
59
|
+
- 挙動不変の担保はテストで行う。preset 宣言を変更すると Quick Mode の実挙動が変わるため、presets の `quickMode` 変更は破壊的変更として扱う。
|
|
60
|
+
- 経緯: WI-353(`allowedCategories` の宣言値是正・契約テスト)→ 本 ADR / WI-377(経路の載せ替えと残り 2 キーの是正)→ WI-378(契約テストの昇格)。
|
|
61
|
+
|
|
62
|
+
## Alternatives
|
|
63
|
+
|
|
64
|
+
1. **adapter の raw 読みを維持し、presets の `quickMode` セクションを削除する。** デッド宣言は消えるが、防御プリセットごとに Quick Mode 強度を変える設計余地を永久に失い、解決済み config から `quickMode` が消えて ADR-007 の Single Source of Truth と矛盾する。
|
|
65
|
+
2. **経路を載せ替え、実効値を preset 宣言(`["L1","L2"]` / `[]`)に合わせる。** 既存プロジェクトの Quick Mode 緩和範囲が無告知で変わる破壊的変更であり、#27 と同種の事故を再発させる。
|
|
66
|
+
3. **`LoadResolvedConfigUseCase` をそのまま呼ぶ(AJV schema 検証込みの完全経路)。** schema 違反 config で Quick Mode 判定が新たに例外を投げるようになり、ADR-038 の fail-open 表を変更してしまう。本 ADR は domain service(`PresetResolutionService`)と preset 定義のみを利用し、検証の厳格度は変えない。
|
|
@@ -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`.
|