phasegate 0.335.0 → 0.341.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 (111) hide show
  1. package/CHANGELOG.md +16 -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/folder_management_rules.md +10 -1
  7. package/docs/guide/antigravity-integration.md +26 -0
  8. package/docs/guide/cli-reference.md +27 -7
  9. package/docs/guide/codex-integration.md +44 -107
  10. package/docs/guide/configuration.md +28 -2
  11. package/docs/guide/grok-integration.md +26 -0
  12. package/docs/guide/hooks-integration.md +34 -5
  13. package/docs/guide/installation.md +4 -2
  14. package/docs/guide/setup-artifacts.md +4 -4
  15. package/docs/guide/skills-overview.md +4 -1
  16. package/package.json +2 -1
  17. package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +1 -1
  18. package/scripts/harness/agent-integration/application/dto/normalized-pre-tool-use-request.ts +32 -0
  19. package/scripts/harness/agent-integration/application/usecases/handle-post-tool-use-usecase.ts +4 -0
  20. package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +38 -3
  21. package/scripts/harness/agent-integration/application/usecases/handle-stop-usecase.ts +3 -9
  22. package/scripts/harness/agent-integration/domain/ports/full-mode-requirement-query-port.ts +3 -1
  23. package/scripts/harness/agent-integration/domain/ports/story-reflection-query-port.ts +2 -0
  24. package/scripts/harness/agent-integration/domain/services/apply-patch-write-target-extractor.ts +98 -0
  25. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +6 -52
  26. package/scripts/harness/agent-integration/domain/services/hook-to-cli-translator.ts +8 -5
  27. package/scripts/harness/agent-integration/domain/value-objects/hook-translation-result.ts +2 -2
  28. package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +35 -18
  29. package/scripts/harness/agent-integration/domain/value-objects/story-reflection-query-result.ts +10 -2
  30. package/scripts/harness/agent-integration/domain/value-objects/write-target-scope.ts +12 -0
  31. package/scripts/harness/agent-integration/infrastructure/adapters/child-process-cli-executor-adapter.ts +64 -13
  32. package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +108 -2
  33. package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +8 -6
  34. package/scripts/harness/agent-integration/presentation/hook-skip-event-recorder.ts +3 -0
  35. package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +1 -1
  36. package/scripts/harness/agent-integration/presentation/post-tool-use-feedback.ts +39 -0
  37. package/scripts/harness/agent-integration/presentation/post-tool-use-hook.ts +21 -27
  38. package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +126 -70
  39. package/scripts/harness/agent-integration/presentation/pre-tool-use-payload-normalizer.ts +228 -0
  40. package/scripts/harness/agent-integration/presentation/pre-tool-use-response-renderer.ts +38 -0
  41. package/scripts/harness/agent-integration/presentation/stop-hook.ts +1 -3
  42. package/scripts/harness/biome-ast-engine/infrastructure/adapters/biome-cli-executor-adapter.ts +21 -1
  43. package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +5 -0
  44. package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +2 -0
  45. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +15 -0
  46. package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +6 -3
  47. package/scripts/harness/harness-api/domain/ports/biome-lint-port.ts +2 -1
  48. package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +12 -1
  49. package/scripts/harness/harness-api/infrastructure/adapters/biome-ast-engine-lint-adapter.ts +10 -2
  50. package/scripts/harness/installation/application/bundled-skill-selection.ts +28 -2
  51. package/scripts/harness/installation/application/checks/antigravity-hook-missing-check.ts +79 -0
  52. package/scripts/harness/installation/application/checks/check-utils.ts +2 -2
  53. package/scripts/harness/installation/application/checks/codex-hook-missing-check.ts +70 -6
  54. package/scripts/harness/installation/application/checks/grok-hook-missing-check.ts +79 -0
  55. package/scripts/harness/installation/application/checks/husky-runtime-inactive-check.ts +33 -0
  56. package/scripts/harness/installation/application/named-hook-json.ts +17 -0
  57. package/scripts/harness/installation/application/operator-notice.ts +42 -0
  58. package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +18 -7
  59. package/scripts/harness/installation/application/usecases/run-install.ts +157 -57
  60. package/scripts/harness/installation/application/usecases/run-reconcile.ts +148 -31
  61. package/scripts/harness/installation/application/usecases/run-uninstall.ts +149 -25
  62. package/scripts/harness/installation/composition-root.ts +10 -0
  63. package/scripts/harness/installation/domain/agent-target.ts +39 -0
  64. package/scripts/harness/installation/domain/check-id.ts +5 -0
  65. package/scripts/harness/installation/domain/husky-runtime-state.ts +34 -0
  66. package/scripts/harness/installation/domain/ports/git-hooks-runtime-probe.ts +9 -0
  67. package/scripts/harness/installation/domain/repair-table.ts +5 -0
  68. package/scripts/harness/installation/infrastructure/adapters/git-hooks-runtime-probe-adapter.ts +62 -0
  69. package/scripts/harness/installation/presentation/cli/install-handler.ts +25 -5
  70. package/scripts/harness/installation/presentation/cli/reconcile-handler.ts +7 -1
  71. package/scripts/harness/installation/presentation/formatters/diagnostic-report-formatter.ts +27 -0
  72. package/scripts/harness/main.ts +227 -128
  73. package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +48 -5
  74. package/scripts/harness/phase-dependency-model/domain/services/work-item-reflection-scope-resolver.ts +64 -0
  75. package/scripts/harness/phase-dependency-model/domain/values/story-reflection-mapping.ts +8 -2
  76. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +6 -1
  77. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-work-item-dependency-catalog.ts +73 -0
  78. package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +5 -1
  79. package/scripts/harness/quick-mode/application/dto/quick-mode-eligibility-contract.ts +1 -1
  80. package/scripts/harness/quick-mode/application/ports/change-risk-advisory-port.ts +16 -0
  81. package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +3 -1
  82. package/scripts/harness/quick-mode/composition-root.ts +5 -1
  83. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +13 -2
  84. package/scripts/harness/quick-mode/domain/types/rejection-rule.ts +1 -1
  85. package/scripts/harness/quick-mode/infrastructure/adapters/snapshot-risk-advisory-adapter.ts +118 -0
  86. package/scripts/harness/quick-mode/presentation/formatters/change-category-formatter.ts +7 -0
  87. package/scripts/harness/quick-mode/presentation/handlers/check-change-category-handler.ts +12 -1
  88. package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +13 -3
  89. package/scripts/harness/setup/skill-deployer.ts +3 -45
  90. package/scripts/harness/skill-quality/application/dto/run-plan-checker-loop-output.ts +1 -0
  91. package/scripts/harness/skill-quality/application/usecases/apply-cascade-update-usecase.ts +9 -4
  92. package/scripts/harness/skill-quality/application/usecases/execute-tdd-cycle-usecase.ts +2 -1
  93. package/scripts/harness/skill-quality/application/usecases/run-plan-checker-loop-usecase.ts +8 -0
  94. package/scripts/harness/skill-quality/composition-root.ts +14 -7
  95. package/scripts/harness/skill-quality/domain/ports/plan-check-executor-port.ts +2 -0
  96. package/scripts/harness/skill-quality/domain/value-objects/cascade-update-target.ts +15 -1
  97. package/scripts/harness/skill-quality/infrastructure/adapters/l1-biome-validator-adapter.ts +9 -1
  98. package/scripts/harness/skill-quality/infrastructure/adapters/l2-validator-system-adapter.ts +18 -2
  99. package/scripts/harness/skill-quality/presentation/handlers/apply-cascade-update-handler.ts +8 -2
  100. package/scripts/harness/skill-quality/presentation/handlers/execute-tdd-cycle-handler.ts +4 -3
  101. package/scripts/harness/skill-quality/presentation/handlers/run-plan-checker-loop-handler.ts +11 -4
  102. package/scripts/harness/traceability-model/infrastructure/parsers/work-item-frontmatter-parser.ts +41 -0
  103. package/skills/README.md +7 -0
  104. package/skills/cascade-updater/SKILL.md +37 -109
  105. package/skills/cascade-updater/references//345/261/244/345/210/245/345/210/244/345/256/232/343/202/254/343/202/244/343/203/211.md +5 -3
  106. package/skills/release-publisher/SKILL.md +3 -1
  107. package/skills/skill-creator/SKILL.md +8 -9
  108. package/templates/.agents/hooks.json +16 -0
  109. package/templates/.claude/scripts/analyze-errors-hook.sh +2 -2
  110. package/templates/.claude/settings.json +5 -3
  111. package/templates/.codex/hooks.json +2 -2
@@ -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)
@@ -1,5 +1,29 @@
1
1
  # Configuration
2
2
 
3
+ ## Work-item dependency declarations
4
+
5
+ <!-- @work-item-id WI-220 -->
6
+
7
+ A WI description may declare direct dependencies in its frontmatter:
8
+
9
+ ```yaml
10
+ depends_on: [WI-123, WI-124]
11
+ ```
12
+
13
+ A block list of WI IDs is also supported. An explicit `depends_on: []` means no declared dependencies; an omitted field means unknown, not an empty dependency set. Do not add empty declarations to old WIs without reviewing their dependencies. This is separate from phase configuration's `dependsOn` and is not evidence of semantic design approval.
14
+
15
+ The dependency-specific reader diagnoses malformed lists, duplicate keys and invalid WI IDs. The existing metadata reader retains its previous behavior; adding this declaration does not itself enable a new blocking gate.
16
+
17
+ For implementation writes permitted by a valid Full Mode session, the candidate runtime checks the session WI and its declared transitive dependencies and prints advisory reflection warnings to stderr. Existing session permission and exit 0 are retained, including when dependency information is incomplete or unreadable. Inception/product edits remain outside this additional check; `storyReflection.enabled: false` disables it. An omitted dependency declaration is reported as unverified, not silently interpreted as no dependencies.
18
+
19
+ The session advisory uses `paths.inceptionDocs` and `paths.designDocs` consistently for dependency discovery, design artifacts, reflection mappings, and legacy aliases. Existing mapping templates retain their canonical `docs/inception/` and `docs/product/construction/` prefixes; this session path resolves those prefixes to the configured roots. Product mappings outside construction, such as `docs/product/units/`, are unchanged. Invalid roots are reported as unverified rather than falling back to default directories. Older non-session reflection calls retain their previous behavior.
20
+
21
+ This checks configured reflection annotations, not semantic approval. A `fix` item needs reflection in at least one configured product candidate per affected unit; choosing the semantically relevant categories remains a review responsibility. Missing required design artifacts are reported as unverified in advisory mode.
22
+
23
+ For the authenticated Full Mode session path, v3 configuration may explicitly select `agentIntegration.preToolUse.dependencyReflection: "enforce"` (or `"advisory"`, the default behavior when omitted). No setting is added automatically. Enforce mode blocks known missing reflection and required artifacts; `storyReflection.enabled: false` still disables this check. Incomplete dependency information falls back to the existing Unit-wide reflection check and reports an unverified warning, even if that fallback passes. Read/configuration failures retain the existing session permission with an unverified warning. This is not a fail-closed semantic approval system.
24
+
25
+ Repair the indicated inception and product documents separately, obtain any required upstream decisions, and retry the implementation operation. WI inception Markdown design repair is no longer subjected to downstream implementation gates; protected-file checks, source-root overlaps, existing shared-plan/description gates, product gates, and implementation paths remain enforced. Do not treat adding a tag alone as design approval. Standard-gate CLI tests cover both unreflected existing product documents and missing product documents followed by repair and resumption.
26
+
3
27
  ## phasegate.config.json
4
28
 
5
29
  Place at project root. Generated by `npx phasegate init`.
@@ -666,9 +690,11 @@ Introduced in ISSUE-007 Wave 1 (v0.65.0) and wired into the pre-tool-use hook by
666
690
 
667
691
  Generate or refresh the snapshot with `npx phasegate baseline` (`--dry-run` to inspect, `--force` to overwrite, `--paths <glob,glob,...>` to scope, `--json` for CI-friendly output). See the [Baseline section in CLI Reference](cli-reference.md#baseline-retrofit-grandfather) for details.
668
692
 
669
- #### `agentIntegration` (Stop hook strict mode)
693
+ #### `agentIntegration` (Hook controls)
694
+
695
+ Controls agent-side hook behavior. In v3 configuration, optional `preToolUse.enabled` and `postToolUse.enabled` boolean values override the legacy `harnesses.agentLessonCollection` and `harnesses.cascadeUpdate` mappings respectively. When omitted, each legacy value is preserved (default `true` when that legacy key is also absent). No existing config is rewritten automatically. These controls do not remove protected-file or trust-root enforcement. <!-- @work-item-id WI-220 -->
670
696
 
671
- Controls how phasegate's agent-side hooks integrate with Claude Code. Currently only `stopHook.enforce` is exposed.
697
+ The independent keys require a version whose v3 schema supports them. Do not add them while older schema readers are still in use. Before downgrading, restore the configuration saved before adding these keys. There is currently no `config:plan` intent for these fields: use a human-reviewed, out-of-agent-hook edit under the trust-root policy rather than asking the agent to rewrite its own protection configuration.
672
698
 
673
699
  ```jsonc
674
700
  {
@@ -0,0 +1,26 @@
1
+ # Grok Build Integration
2
+
3
+ <!-- @work-item-id WI-385 -->
4
+
5
+ Phasegate uses Grok Build's Claude-compatible project hook scanner. It manages `.claude/settings.json` as the single hook source and deliberately does not create `.grok/hooks`, avoiding duplicate invocation.
6
+
7
+ Minimum supported runtime: the hook-capable Grok CLI 1.0.0 series, which is the series used to verify this integration. If hooks appear to be silently inactive, run `grok inspect` and confirm the project hook is loaded and trusted in `/hooks`.
8
+
9
+ ## Setup
10
+
11
+ ```bash
12
+ npx phasegate install --agent grok --with-husky --apply
13
+ npx phasegate doctor --agent grok
14
+ ```
15
+
16
+ The managed PreToolUse entries collectively match `Bash|Write|Edit|apply_patch`; each Phasegate command has an explicit 30-second timeout. Grok otherwise defaults a hook to 5 seconds and fails open when the hook times out or crashes, so the distributed timeout gives Phasegate enough time to inspect a write while L2 pre-commit remains the backstop. `run_terminal_command`, `search_replace`, `write`, and `apply_patch` camelCase payloads are normalized to the existing Bash/Write/Edit/patch pipeline. Grok truncates tool input at 128 KB; a truncated command or patch is denied because the full target set cannot be proven. A direct tool with a complete path can still be checked.
17
+
18
+ ## Result contract
19
+
20
+ - Deny writes top-level `{ "decision": "deny", "reason": ... }` and Claude-compatible `hookSpecificOutput` to stdout, writes the reason to stderr, and exits 2.
21
+ - Allow exits 0 with empty stdout and does not override permission.
22
+ - Agent/model fields and the selected install target are not authorization inputs.
23
+
24
+ ## Trust and residual risk
25
+
26
+ Project hooks can be skipped before trust is approved, and Phasegate cannot inspect Grok's external trust state. Run `grok inspect`, open `/hooks`, and approve with `--trust` or `/hooks-trust`. Keep L2 pre-commit and CI enabled because timeout/crash remains fail-open even with the explicit 30-second limit. The canonical path key for every future Grok `write` variant remains runtime-controlled; unknown supported-write shapes fail closed rather than silently allowing.
@@ -6,17 +6,28 @@ Phasegate integrates natively with Claude Code through its hooks system. This en
6
6
 
7
7
  For new or existing projects, prefer `npx phasegate install --dry-run` followed by `npx phasegate install --apply` so existing hook JSON is merged instead of replaced. Manual editing is still possible, but then `phasegate doctor` may report missing managed targets until the expected PhaseGate entries, skill links, Husky scripts, CI workflow, and manifest are present. See [Setup Artifacts](setup-artifacts.md). <!-- @work-item-id WI-152 --> <!-- @work-item-id WI-169 -->
8
8
 
9
- Add the following to `.claude/settings.json`:
9
+ ### Manual hook configuration
10
+
11
+ If structured install is unavailable, use the same packaged commands and timeout as the distributed `.claude/settings.json`:
10
12
 
11
13
  ```jsonc
12
14
  {
13
15
  "hooks": {
14
16
  "PreToolUse": [
17
+ {
18
+ "matcher": "Bash|apply_patch",
19
+ "hooks": [{
20
+ "type": "command",
21
+ "command": "npx phasegate hook pre-tool-use",
22
+ "timeout": 30
23
+ }]
24
+ },
15
25
  {
16
26
  "matcher": "Write|Edit",
17
27
  "hooks": [{
18
28
  "type": "command",
19
- "command": "npx tsx scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts"
29
+ "command": "npx phasegate hook pre-tool-use",
30
+ "timeout": 30
20
31
  }]
21
32
  }
22
33
  ],
@@ -25,7 +36,7 @@ Add the following to `.claude/settings.json`:
25
36
  "matcher": "Write|Edit",
26
37
  "hooks": [{
27
38
  "type": "command",
28
- "command": "npx tsx scripts/harness/agent-integration/presentation/post-tool-use-hook.ts"
39
+ "command": "npx phasegate hook post-tool-use"
29
40
  }]
30
41
  }
31
42
  ],
@@ -34,7 +45,7 @@ Add the following to `.claude/settings.json`:
34
45
  "matcher": "",
35
46
  "hooks": [{
36
47
  "type": "command",
37
- "command": "npx tsx scripts/harness/agent-integration/presentation/stop-hook.ts"
48
+ "command": "npx phasegate hook stop"
38
49
  }]
39
50
  }
40
51
  ]
@@ -42,6 +53,18 @@ Add the following to `.claude/settings.json`:
42
53
  }
43
54
  ```
44
55
 
56
+ ## Runtime coverage matrix
57
+
58
+ <!-- @work-item-id WI-385 -->
59
+
60
+ | Runtime payload | Managed source | Pre-edit deny output | Coverage boundary |
61
+ |---|---|---|---|
62
+ | Claude / Codex flat snake_case | `.claude/settings.json` / `.codex/hooks.json` | empty stdout, stderr, exit 2 | Existing contract unchanged |
63
+ | Grok flat camelCase | Claude-compatible `.claude/settings.json` | top-level deny plus `hookSpecificOutput`, stderr, exit 2 | Trust must be checked with `grok inspect` / `/hooks` |
64
+ | Antigravity nested `toolCall` | named `.agents/hooks.json` | top-level `decision` / `reason`, stderr, exit 2 | Hard block supported for `agy` CLI only |
65
+
66
+ All allow paths keep stdout empty and do not override runtime permission. Malformed, ambiguous, truncated command/patch, or supported write tools without extractable targets fail closed. L2 pre-commit and CI remain the backstops for untrusted/skipped hooks, Antigravity IDE/desktop, and unverified timeout/crash behavior.
67
+
45
68
  ## Hook Behaviors
46
69
 
47
70
  ### Responsibility Separation (important)
@@ -59,7 +82,7 @@ This separation is intentional:
59
82
  - **Post = "is what was written valid?"** — concerns the resulting code's quality.
60
83
  - **Stop = "is the session ready to end?"** — concerns the cumulative state across the session.
61
84
 
62
- If you expect L1 lint (e.g., missing `@unit` annotation) to **block** a Write before it happens, that is by design **not** the case. The PreToolUse hook intentionally does not run lint, because lint requires the resulting file content (which only exists after the write). Lint violations surface as **PostToolUse** decision JSON (`decision: "block"`) and trigger Claude Code to retry.
85
+ The PreToolUse hook does not run lint, because lint requires the resulting file content. The packaged `phasegate hook post-tool-use` command reports lint failures as advisory stderr with exit 0; it does not emit a block decision or request automatic retries. Separate shell hooks such as `analyze-errors-hook.sh` have their own output contract and are not changed by this packaged-command behavior. Commit and CI checks remain independent enforcement points.
63
86
 
64
87
  ### PreToolUse (before file write)
65
88
  - Enforces Phase Gate: blocks writing to source files if required design documents don't exist
@@ -91,6 +114,12 @@ Use /quick-implementor skill for version changes in package.json.
91
114
  - Runs Biome AST rules automatically
92
115
  - Provides immediate feedback on violations
93
116
 
117
+ <!-- @work-item-id WI-220 -->
118
+
119
+ The packaged command resolves direct-edit and complete patch targets relative to the payload's working directory, then runs lint from the project's configuration root. Multiple targets are retained. Analysis keeps the full dependency graph; only the reported diagnostics are scoped. Unknown shell commands and incomplete targets retain full lint rather than a potentially incomplete target list.
120
+
121
+ Read/Glob/Grep and disabled hooks finish silently without starting lint. The lint subprocess has a five-second limit; timeout is reported as **validation incomplete**, not a pass. It does not automatically retry. Run `phasegate lint` explicitly when ready to complete validation. This timeout covers the child lint process, not the host runtime's own hook timeout.
122
+
94
123
  ### Stop (before session end)
95
124
  - Runs `phasegate:complete-check` (L2-L4 full validation)
96
125
  - The built-in Stop hook runs the packaged PhaseGate CLI command; downstream projects do not need to provide `scripts/harness/cli/complete-check.ts`.
@@ -36,7 +36,7 @@ npm install
36
36
  npx phasegate init --name <project-name>
37
37
  ```
38
38
 
39
- This deploys 29 skills to `skills/`, creates the agent-facing skill links (for example `.claude/skills/` or `.codex/skills/`), and generates `phasegate.config.json`.
39
+ This deploys 29 skills to `skills/`, creates the selected agent-facing skill links (`.claude/skills/`, `.codex/skills/`, or `.agents/skills/`), and generates `phasegate.config.json`.
40
40
 
41
41
  `init` is the legacy-compatible bootstrap path for new projects. It also runs the structured install path for the selected agent target so `CLAUDE.md` and/or `AGENTS.md` receive a PhaseGate managed section. Use `install` when the project may already have hooks, package scripts, or CI files that should be preserved. <!-- @work-item-id WI-174 -->
42
42
 
@@ -56,7 +56,9 @@ npx phasegate install --apply
56
56
  npx phasegate doctor
57
57
  ```
58
58
 
59
- `install --dry-run` reports whether each target will be created, merged, skipped, or refused. `install --apply` performs the merge, adds package scripts and the `phasegate` devDependency, deploys selected bundled skills to root `skills/`, creates `.claude/skills` and `.codex/skills` links, writes `CLAUDE.md` / `AGENTS.md` managed sections for selected agent targets, writes `.github/workflows/phasegate-aidlc-gate.yml` when CI is enabled, and records managed entries in `.phasegate/manifest.json`. Husky hook targets (`.husky/*`) and the GitHub Actions target are opt-in, matching `init` and `setup:agent`: pass `--with-husky` and/or `--with-ci` to include them — without these flags `install` does not touch `.husky/` or `.github/workflows/`. <!-- @work-item-id WI-316 --> Existing skills catalogs are merged: PhaseGate refreshes only bundled skill directories selected by `--skills core|all` and preserves user-owned skills. See [Setup Artifacts](setup-artifacts.md) for the full managed target, generated artifact, runtime state, legacy artifact, and user-level setting inventory. <!-- @work-item-id WI-152 --> <!-- @work-item-id WI-169 --> <!-- @work-item-id WI-174 --> <!-- @work-item-id WI-216 -->
59
+ `install --dry-run` reports whether each target will be created, merged, skipped, or refused. `install --apply` performs the merge, adds package scripts and the `phasegate` devDependency, deploys selected bundled skills to root `skills/`, creates the selected `.claude/skills`, `.codex/skills`, and `.agents/skills` links, writes `CLAUDE.md` / `AGENTS.md` managed sections for selected agent targets, writes `.github/workflows/phasegate-aidlc-gate.yml` when CI is enabled, and records managed entries in `.phasegate/manifest.json`. Husky hook targets (`.husky/*`) and the GitHub Actions target are opt-in, matching `init` and `setup:agent`: pass `--with-husky` and/or `--with-ci` to include them — without these flags `install` does not touch `.husky/` or `.github/workflows/`. <!-- @work-item-id WI-316 --> Existing skills catalogs are merged: PhaseGate refreshes only bundled skill directories selected by `--skills core|all` and preserves user-owned skills. See [Setup Artifacts](setup-artifacts.md) for the full managed target, generated artifact, runtime state, legacy artifact, and user-level setting inventory. <!-- @work-item-id WI-152 --> <!-- @work-item-id WI-169 --> <!-- @work-item-id WI-174 --> <!-- @work-item-id WI-216 -->
60
+
61
+ Agent targets are `claude | codex | both | grok | antigravity | all`. `both` is backward-compatible Claude + Codex. Grok shares `.claude/settings.json` and `.claude/skills`, receives `AGENTS.md` without Claude-only `CLAUDE.md`, and does not receive `.grok/hooks`. Antigravity receives `.agents/hooks.json`, `.agents/skills`, and `AGENTS.md`. `all` installs Claude, Codex, and Antigravity surfaces, with Grok covered once by the Claude-compatible hook. <!-- @work-item-id WI-385 -->
60
62
 
61
63
  For personal evaluation inside a team-owned repository:
62
64
 
@@ -14,7 +14,7 @@ PhaseGate setup is more than `phasegate.config.json`. A healthy installation is
14
14
 
15
15
  | Class | Examples | Owner | Lifecycle |
16
16
  |---|---|---|---|
17
- | Managed target | `phasegate.config.json`, `.claude/settings.json`, `.codex/hooks.json`, `CLAUDE.md`, `AGENTS.md`, `.husky/pre-commit`, `.husky/commit-msg`, `.husky/pre-push`, `.github/workflows/phasegate-aidlc-gate.yml`, root `skills/` bundled skill bodies, `.claude/skills`, `.codex/skills`, `package.json` PhaseGate scripts/devDependency | PhaseGate managed block, real runtime artifact, shared skill body, or symlink plus user content | Created or merged by `install`, refreshed by `reconcile`, removed or reversed by `uninstall` |
17
+ | Managed target | `phasegate.config.json`, `.claude/settings.json`, `.codex/hooks.json`, `.agents/hooks.json`, `CLAUDE.md`, `AGENTS.md`, `.husky/pre-commit`, `.husky/commit-msg`, `.husky/pre-push`, `.github/workflows/phasegate-aidlc-gate.yml`, root `skills/` bundled skill bodies, `.claude/skills`, `.codex/skills`, `.agents/skills`, `package.json` PhaseGate scripts/devDependency | PhaseGate managed block, real runtime artifact, shared skill body, or symlink plus user content | Created or merged by `install`, refreshed by `reconcile`, removed or reversed by `uninstall` |
18
18
  | Configuration | `phasegate.config.json`, `package.json` | User owned, PhaseGate assisted | Created by `init` or project install when absent; `install` may merge scripts/devDependency into `package.json` |
19
19
  | Generated artifact | `.phasegate/manifest.json`, `.phasegate/backups/*`, `.phasegate/uninstalled-*.json`, `.phasegate/baseline.json` | PhaseGate | Written by lifecycle commands and validators; safe to regenerate only through the owning command |
20
20
  | Runtime state/report | `.phasegate/hook-skip-events.jsonl`, explicit `doctor --report-out <path>` output, `reports/regression/*`, resolved `reporting.outputDir` reports | PhaseGate command output | Produced while hooks, doctor, and validation commands run |
@@ -26,11 +26,11 @@ PhaseGate setup is more than `phasegate.config.json`. A healthy installation is
26
26
 
27
27
  `install --apply` and `reconcile --apply` manage only explicit targets. The current structured lifecycle covers:
28
28
 
29
- - Agent hook JSON: `.claude/settings.json`, `.codex/hooks.json`
29
+ - Agent hook JSON: `.claude/settings.json`, `.codex/hooks.json`, `.agents/hooks.json`
30
30
  - Agent context files: `CLAUDE.md` and `AGENTS.md` managed sections. `AGENT.md` singular is not a PhaseGate managed target; treat it as user-owned content or migrate it manually. <!-- @work-item-id WI-174 -->
31
31
  - Husky scripts when requested: `.husky/pre-commit`, `.husky/commit-msg`, `.husky/pre-push`
32
32
  - CI workflow when requested: `.github/workflows/phasegate-aidlc-gate.yml`
33
- - Agent skill links: `.claude/skills`, `.codex/skills`
33
+ - Agent skill links: `.claude/skills`, `.codex/skills`, `.agents/skills`
34
34
  - Project shared bundled skills: selected `skills/<name>/` directories plus `skills/.harness-version`
35
35
  - Project config: `phasegate.config.json` when absent, so installed agent hooks have a discoverable runtime config
36
36
  - Package metadata: PhaseGate scripts and `devDependencies.phasegate` in `package.json`
@@ -48,7 +48,7 @@ If `.claude/*` or `.codex/*` already exists and is not a PhaseGate-managed perso
48
48
 
49
49
  Personal agent context is also placed only where the runtime will read it. Claude Code uses `.claude/CLAUDE.md`. Codex uses root `AGENTS.md` when PhaseGate can create or manage it locally; if a team `AGENTS.md` already exists, PhaseGate leaves it unchanged and doctor reports `codex-context-missing` instead of creating `AGENTS.override.md`. <!-- @work-item-id WI-215 -->
50
50
 
51
- Project install uses a different topology: selected bundled skills are deployed once to root `skills/`, and `.claude/skills` / `.codex/skills` point to that shared target. Existing root `skills/` is also a mergeable catalog: selected bundled skill directories are refreshed, selection-excluded or user-owned skills are not removed, and uninstall deletes only manifest-managed bundled skills plus metadata. If an older project install has the links but an empty `skills/` target, `phasegate doctor` reports the selected agent skill check and `phasegate reconcile --apply` repairs the shared skill bodies. <!-- @work-item-id WI-210 --> <!-- @work-item-id WI-216 -->
51
+ Project install uses a different topology: selected bundled skills are deployed once to root `skills/`, and `.claude/skills` / `.codex/skills` / `.agents/skills` point to that shared target. Existing root `skills/` is also a mergeable catalog: selected bundled skill directories are refreshed, selection-excluded or user-owned skills are not removed, and uninstall deletes only manifest-managed bundled skills plus metadata. If an older project install has the links but an empty `skills/` target, `phasegate doctor` reports the selected agent skill check and `phasegate reconcile --apply` repairs the shared skill bodies. <!-- @work-item-id WI-210 --> <!-- @work-item-id WI-216 -->
52
52
 
53
53
  ## Doctor Findings
54
54
 
@@ -1,6 +1,9 @@
1
1
  # Skills Overview
2
2
 
3
- Phasegate provides 29 skills covering the full AIDLC (AI-Driven Development Life Cycle). `npx phasegate init` and project `npx phasegate install` deploy skill bodies to root `skills/` and expose them to enabled agents through `.claude/skills/` / `.codex/skills/` links. Personal install instead writes real local-only per-agent skill directories. <!-- @work-item-id WI-210 -->
3
+ <!-- @work-item-id WI-223 -->
4
+ For consumer projects, explicitly select `phasegate install --skills consumer --dry-run` (then `--apply` after review). This deploys 27 skills, excluding the Phasegate-maintainer-only `release-publisher` and `skill-creator`. Legacy `core` (7), `all` (29), and the omitted-option default (`all`) remain unchanged. `init` also accepts `consumer`. Reconcile preserves the set recorded in each skill root's `.harness-version`; missing/invalid/unknown metadata retains the legacy `all` fallback. Changing sets does not delete previously installed or user-owned skills. This is audience separation, not a claim of language-independent test tooling.
5
+
6
+ Phasegate provides 29 skills covering the full AIDLC (AI-Driven Development Life Cycle). `npx phasegate init` and project `npx phasegate install` deploy skill bodies to root `skills/` and expose them to enabled agents through `.claude/skills/`, `.codex/skills/`, or `.agents/skills/` links. Personal install instead writes real local-only per-agent skill directories. <!-- @work-item-id WI-210 --> <!-- @work-item-id WI-385 -->
4
7
 
5
8
  Bundled `SKILL.md` files include `languages: [typescript]` frontmatter so PhaseGate can distinguish current TypeScript-oriented guidance from future language-specific skill variants. The metadata is advisory for applicability and does not prevent non-TypeScript projects from installing the catalog. <!-- @work-item-id WI-212 -->
6
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phasegate",
3
- "version": "0.335.0",
3
+ "version": "0.341.0",
4
4
  "packageManager": "pnpm@10.30.1",
5
5
  "description": "Phasegate — AI-agnostic quality defense toolkit. Enforces structural integrity between design intent and code.",
6
6
  "license": "MIT",
@@ -47,6 +47,7 @@
47
47
  "phasegate": "bin/phasegate"
48
48
  },
49
49
  "scripts": {
50
+ "pack:runtime": "node scripts/pack-runtime.mjs",
50
51
  "phasegate": "npx tsx scripts/harness/main.ts",
51
52
  "phasegate:status": "npx tsx scripts/harness/main.ts phasegate:status",
52
53
  "phasegate:enable": "npx tsx scripts/harness/main.ts enable-feature",
@@ -26,7 +26,7 @@ export interface HandlePreToolUseOutput {
26
26
  phaseGateBlockers?: string[];
27
27
  storyReflectionBlockers?: string[];
28
28
  storyReflectionWarnings?: string[];
29
- fullModeRejectionRule?: 'MIXED_CHANGES' | 'NEW_DOMAIN' | 'API_CONTRACT';
29
+ fullModeRejectionRule?: 'CATEGORY_NOT_ALLOWED' | 'MIXED_CHANGES' | 'NEW_DOMAIN' | 'API_CONTRACT';
30
30
  fullModeDominantCategory?: string;
31
31
  nextAction?: string;
32
32
  // Quick Mode が write を許可した際に dominant カテゴリを presentation 層に伝える。
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @unit agent-integration
3
+ * @layer application
4
+ * @work-item-id WI-385
5
+ */
6
+
7
+ export type PayloadShape = "FLAT_SNAKE_CASE" | "FLAT_CAMEL_CASE" | "NESTED_TOOL_CALL";
8
+
9
+ export type HookResponseProfile = "LEGACY_EXIT_ONLY" | "COMPATIBILITY_DENY_ENVELOPE" | "TOP_LEVEL_DENY_ENVELOPE";
10
+
11
+ export interface CanonicalPreToolUseInput {
12
+ readonly path?: string;
13
+ readonly file_path?: string;
14
+ readonly paths?: readonly string[];
15
+ readonly command?: string;
16
+ readonly content?: string;
17
+ readonly old_string?: string;
18
+ readonly new_string?: string;
19
+ }
20
+
21
+ export interface NormalizedPreToolUseRequest {
22
+ readonly shape: PayloadShape;
23
+ readonly responseProfile: HookResponseProfile;
24
+ readonly cwd?: string;
25
+ readonly toolName: string;
26
+ readonly toolInput: CanonicalPreToolUseInput;
27
+ readonly inputTruncated: boolean;
28
+ }
29
+
30
+ export type PreToolUseNormalizationResult =
31
+ | { readonly ok: true; readonly request: NormalizedPreToolUseRequest }
32
+ | { readonly ok: false; readonly reason: string; readonly responseProfile?: HookResponseProfile };
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @layer application
3
3
  * @unit agent-integration
4
+ * @work-item-id WI-220
4
5
  * @story H11-03
5
6
  *
6
7
  * HandlePostToolUseUseCase
@@ -39,6 +40,9 @@ export class HandlePostToolUseUseCase {
39
40
  }
40
41
 
41
42
  async execute(input: HandlePostToolUseInput): Promise<HandlePostToolUseOutput> {
43
+ if (input.affectedFilePaths.length === 0 && ['Read', 'Glob', 'Grep'].includes(input.toolName)) {
44
+ return { executed: false, skipReason: 'READ_ONLY' };
45
+ }
42
46
  const hookEvent = HookEvent.createPostToolUse(input.toolName, input.affectedFilePaths);
43
47
  const translationResult = await this.translator.translate(hookEvent);
44
48