agent-write-gate 0.1.0__tar.gz
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.
- agent_write_gate-0.1.0/LICENSE +21 -0
- agent_write_gate-0.1.0/PKG-INFO +276 -0
- agent_write_gate-0.1.0/README.md +249 -0
- agent_write_gate-0.1.0/pyproject.toml +36 -0
- agent_write_gate-0.1.0/setup.cfg +4 -0
- agent_write_gate-0.1.0/src/agent_write_gate.egg-info/PKG-INFO +276 -0
- agent_write_gate-0.1.0/src/agent_write_gate.egg-info/SOURCES.txt +29 -0
- agent_write_gate-0.1.0/src/agent_write_gate.egg-info/dependency_links.txt +1 -0
- agent_write_gate-0.1.0/src/agent_write_gate.egg-info/entry_points.txt +2 -0
- agent_write_gate-0.1.0/src/agent_write_gate.egg-info/requires.txt +9 -0
- agent_write_gate-0.1.0/src/agent_write_gate.egg-info/top_level.txt +1 -0
- agent_write_gate-0.1.0/src/agentgate/__init__.py +5 -0
- agent_write_gate-0.1.0/src/agentgate/adapter.py +142 -0
- agent_write_gate-0.1.0/src/agentgate/apply_patch.py +74 -0
- agent_write_gate-0.1.0/src/agentgate/checks/__init__.py +1 -0
- agent_write_gate-0.1.0/src/agentgate/checks/cjk.py +81 -0
- agent_write_gate-0.1.0/src/agentgate/checks/unicode_safety.py +277 -0
- agent_write_gate-0.1.0/src/agentgate/cli.py +550 -0
- agent_write_gate-0.1.0/src/agentgate/config.py +171 -0
- agent_write_gate-0.1.0/src/agentgate/model.py +34 -0
- agent_write_gate-0.1.0/src/agentgate/policy.py +94 -0
- agent_write_gate-0.1.0/src/agentgate/registry.py +61 -0
- agent_write_gate-0.1.0/src/agentgate/report.py +247 -0
- agent_write_gate-0.1.0/tests/test_adapter.py +155 -0
- agent_write_gate-0.1.0/tests/test_apply_patch.py +129 -0
- agent_write_gate-0.1.0/tests/test_cjk_integration.py +218 -0
- agent_write_gate-0.1.0/tests/test_hook_exit.py +124 -0
- agent_write_gate-0.1.0/tests/test_policy.py +140 -0
- agent_write_gate-0.1.0/tests/test_scan.py +125 -0
- agent_write_gate-0.1.0/tests/test_unicode_check.py +197 -0
- agent_write_gate-0.1.0/tests/test_unicode_falsepos.py +264 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hryoma1217
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-write-gate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent-hook safety gate for AI-written code -- blocks bidi/invisible Unicode and CJK corruption at the write boundary
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: agent,hook,safety,unicode,cjk,llm,claude-code,codex,pre-commit
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
|
22
|
+
Provides-Extra: cjk
|
|
23
|
+
Requires-Dist: mojihen>=0.1; extra == "cjk"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# agentgate
|
|
29
|
+
|
|
30
|
+
An agent-hook safety gate for AI-written code. Wire it into Claude Code or Codex
|
|
31
|
+
as a hook; it runs a battery of deterministic checks on the text an agent is about
|
|
32
|
+
to write (PreToolUse) or just wrote (PostToolUse) and either blocks the write or
|
|
33
|
+
hands the model a structured feedback blob so the loop self-corrects without a
|
|
34
|
+
human round-trip.
|
|
35
|
+
|
|
36
|
+
## Problem
|
|
37
|
+
|
|
38
|
+
AI coding agents write files directly. They introduce defect classes that
|
|
39
|
+
traditional linters and CI were not built to catch:
|
|
40
|
+
|
|
41
|
+
- **Valid-but-wrong CJK** -- a real but wrong kanji/hanzi/hangul (mojihen's
|
|
42
|
+
domain; grep and unit tests pass it as false-green).
|
|
43
|
+
- **Bidi / invisible Unicode** -- Trojan-Source bidi overrides and invisible
|
|
44
|
+
characters smuggled into source identifiers.
|
|
45
|
+
|
|
46
|
+
Both have standalone CLIs that run in CI. What is missing is a single hook at
|
|
47
|
+
the agent write boundary that (a) speaks the agents' hook protocols, (b) applies
|
|
48
|
+
one severity-to-action policy across checks, and (c) returns a model-readable
|
|
49
|
+
feedback blob so the agent rewrites itself.
|
|
50
|
+
|
|
51
|
+
## Positioning (honest)
|
|
52
|
+
|
|
53
|
+
agentgate is not a new category -- Claude Code and Codex already expose hook
|
|
54
|
+
frameworks. agentgate is the packaged, cross-agent gate that bundles
|
|
55
|
+
AI-write-specific checks, normalizes the two agents' payloads, centralizes
|
|
56
|
+
block/warn policy, and ships an open check registry so the set grows without
|
|
57
|
+
forking. The ecosystem value is the gate + registry standard, plus composing the
|
|
58
|
+
sibling engine mojihen, not any single linter.
|
|
59
|
+
|
|
60
|
+
## Coverage limits
|
|
61
|
+
|
|
62
|
+
agentgate only sees writes that flow through a hooked tool call. It does NOT see,
|
|
63
|
+
and makes no claim about:
|
|
64
|
+
|
|
65
|
+
- Files written by shell commands the agent runs (`echo >`, `sed -i`, codegen).
|
|
66
|
+
- Pre-existing files, generated artifacts, or out-of-band edits.
|
|
67
|
+
- Editor/IDE agents that do not emit the supported hook payloads.
|
|
68
|
+
- Codex tool paths other than `apply_patch` (best-effort; fail-open otherwise).
|
|
69
|
+
- Anything a PostToolUse hook is asked to undo -- it cannot roll back a completed
|
|
70
|
+
write, only report it back to the model.
|
|
71
|
+
|
|
72
|
+
## M1 built-in checks
|
|
73
|
+
|
|
74
|
+
### unicode (stdlib, always available)
|
|
75
|
+
|
|
76
|
+
- **AG-BIDI** (high, always block): bidi control characters U+202A-U+202E,
|
|
77
|
+
U+2066-U+2069. These are the Trojan-Source vectors with essentially no
|
|
78
|
+
legitimate use in source files.
|
|
79
|
+
- **AG-INVIS** (high, code context only): invisible chars (U+200B zero-width
|
|
80
|
+
space, U+2060 word joiner, U+FEFF stray BOM, U+00AD soft hyphen) flagged only
|
|
81
|
+
when the file has a code extension AND the char is inside an identifier/string
|
|
82
|
+
run. U+200C/U+200D (ZWNJ/ZWJ) and U+200E/U+200F (LRM/RLM) are NOT flagged
|
|
83
|
+
by default -- they are legitimate in Arabic/Persian/Indic text and emoji ZWJ
|
|
84
|
+
sequences. Strict mode (`unicode.strict_zerowidth = true`) adds ZWNJ/ZWJ only
|
|
85
|
+
inside ASCII-identifier runs.
|
|
86
|
+
- **AG-HOMO** (medium, opt-in): Latin-looking Cyrillic/Greek codepoints inside
|
|
87
|
+
an otherwise-ASCII identifier. Off by default.
|
|
88
|
+
|
|
89
|
+
### cjk (requires mojihen extra)
|
|
90
|
+
|
|
91
|
+
Embeds `mojihen.detect.run_detectors` to catch known LLM CJK corruption: a
|
|
92
|
+
real but wrong kanji/hanzi that grep and unit tests pass as false-green (rule
|
|
93
|
+
MH001 and others). Disabled by default so the stdlib-only core installs and runs
|
|
94
|
+
out of the box.
|
|
95
|
+
|
|
96
|
+
## Install
|
|
97
|
+
|
|
98
|
+
Core (stdlib-only, unicode check):
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
pip install agent-write-gate
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
With CJK check (requires mojihen):
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
pip install agent-write-gate[cjk]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then enable in config:
|
|
111
|
+
|
|
112
|
+
```toml
|
|
113
|
+
# agentgate.toml
|
|
114
|
+
[checks]
|
|
115
|
+
cjk = true
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## CLI
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
# Primary: agent hook entrypoint (pipe JSON from agent hook system)
|
|
122
|
+
agentgate hook --stdin
|
|
123
|
+
|
|
124
|
+
# Scan files (CI / manual audit)
|
|
125
|
+
agentgate scan src/ --format tty|json|sarif
|
|
126
|
+
|
|
127
|
+
# List checks and their status
|
|
128
|
+
agentgate checks
|
|
129
|
+
|
|
130
|
+
# Version
|
|
131
|
+
agentgate --version
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Exit codes:
|
|
135
|
+
- `hook`: 0 = allow; 2 = block (deny in Pre / feedback in Post) or error.
|
|
136
|
+
- `scan`: 0 = no blocking findings; 1 = blocking findings; 2 = error.
|
|
137
|
+
|
|
138
|
+
## Hook setup: Claude Code
|
|
139
|
+
|
|
140
|
+
Add to `.claude/settings.json`:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"hooks": {
|
|
145
|
+
"PreToolUse": [
|
|
146
|
+
{
|
|
147
|
+
"matcher": "Write|Edit",
|
|
148
|
+
"hooks": [{"type": "command", "command": "agentgate hook --stdin"}]
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**PreToolUse** (exit 2) denies the tool call -- the write never happens.
|
|
156
|
+
**PostToolUse** (exit 2) surfaces feedback to the model after the write.
|
|
157
|
+
Only PreToolUse provides true prevention. See `hooks/claude-code.md`.
|
|
158
|
+
|
|
159
|
+
## Hook setup: Codex
|
|
160
|
+
|
|
161
|
+
Only `apply_patch` is supported (Codex's primary write tool):
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"hooks": {
|
|
166
|
+
"PreToolUse": [
|
|
167
|
+
{
|
|
168
|
+
"matcher": "apply_patch",
|
|
169
|
+
"hooks": [{"type": "command", "command": "agentgate hook --stdin"}]
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
See `hooks/codex.md` for PostToolUse setup and coverage limits.
|
|
177
|
+
|
|
178
|
+
## pre-commit
|
|
179
|
+
|
|
180
|
+
```yaml
|
|
181
|
+
# .pre-commit-config.yaml
|
|
182
|
+
repos:
|
|
183
|
+
- repo: https://github.com/hryoma1217/agentgate
|
|
184
|
+
rev: v0.1.0
|
|
185
|
+
hooks:
|
|
186
|
+
- id: agentgate
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The bidi / invisible-Unicode checks work out of the box. The CJK corruption
|
|
190
|
+
check is **off by default**; if you enable it (`[checks.cjk] enabled = true`), the
|
|
191
|
+
hook also needs `mojihen` in pre-commit's isolated env — add it via
|
|
192
|
+
`additional_dependencies`:
|
|
193
|
+
|
|
194
|
+
```yaml
|
|
195
|
+
- id: agentgate
|
|
196
|
+
additional_dependencies: ["agent-write-gate[cjk]"]
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Configuration
|
|
200
|
+
|
|
201
|
+
`agentgate.toml` or `[tool.agentgate]` in `pyproject.toml`. Falls back to
|
|
202
|
+
defaults when no config file is found.
|
|
203
|
+
|
|
204
|
+
```toml
|
|
205
|
+
# Unicode checks are ON by default; the CJK check is OFF by default.
|
|
206
|
+
# Enable CJK only if you installed the `agent-write-gate[cjk]` extra.
|
|
207
|
+
[checks.cjk]
|
|
208
|
+
enabled = false
|
|
209
|
+
min_confidence = "high"
|
|
210
|
+
|
|
211
|
+
[checks.unicode]
|
|
212
|
+
enabled = true
|
|
213
|
+
homoglyph = false
|
|
214
|
+
strict_zerowidth = false
|
|
215
|
+
allow_bidi_suppression = false
|
|
216
|
+
code_extensions = [
|
|
217
|
+
".py", ".js", ".ts", ".go", ".rs", ".java",
|
|
218
|
+
".c", ".cpp", ".rb", ".php", ".sh", ".sql"
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
[policy]
|
|
222
|
+
high = "block"
|
|
223
|
+
medium = "warn"
|
|
224
|
+
low = "ignore"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Suppression
|
|
228
|
+
|
|
229
|
+
Rule-specific only: `agentgate: ignore[AG-INVIS]` on the offending line.
|
|
230
|
+
**There is no bare `agentgate: ignore`** -- that would let a model launder
|
|
231
|
+
violations. AG-BIDI is not suppressible unless `allow_bidi_suppression = true`.
|
|
232
|
+
|
|
233
|
+
## Model-readable block report
|
|
234
|
+
|
|
235
|
+
When a write is blocked, stderr looks like:
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
agentgate: BLOCKED -- 2 issue(s) to fix before this write
|
|
239
|
+
|
|
240
|
+
app.py:3:18 cjk/MH001 HIGH '闾' -> likely: 閾
|
|
241
|
+
'闾' is a known LLM corruption (likely intended: 閾) ...
|
|
242
|
+
app.py:5:1 unicode/AG-BIDI HIGH U+202E RIGHT-TO-LEFT OVERRIDE
|
|
243
|
+
Remove the bidi control char; it visually reorders source.
|
|
244
|
+
|
|
245
|
+
Fix these and re-emit.
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The model sees this as a structured remediation signal and issues a corrective
|
|
249
|
+
write without human intervention.
|
|
250
|
+
|
|
251
|
+
## Relationship to mojihen
|
|
252
|
+
|
|
253
|
+
mojihen is the CJK engine (its own PyPI package, independently useful).
|
|
254
|
+
agentgate is the cross-agent gate that composes it (optional extra
|
|
255
|
+
`agent-write-gate[cjk]`) with the stdlib Unicode-safety check, under one policy and
|
|
256
|
+
one model-readable feedback contract. Two focused packages; the gate + open
|
|
257
|
+
registry is the ecosystem layer.
|
|
258
|
+
|
|
259
|
+
## Open registry
|
|
260
|
+
|
|
261
|
+
Third-party checks can be registered:
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
from agentgate.registry import register
|
|
265
|
+
|
|
266
|
+
def my_check(event, cfg):
|
|
267
|
+
# event: WriteEvent, cfg: GateConfig
|
|
268
|
+
# return List[Issue]
|
|
269
|
+
return []
|
|
270
|
+
|
|
271
|
+
register("my-check", my_check)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## License
|
|
275
|
+
|
|
276
|
+
MIT
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# agentgate
|
|
2
|
+
|
|
3
|
+
An agent-hook safety gate for AI-written code. Wire it into Claude Code or Codex
|
|
4
|
+
as a hook; it runs a battery of deterministic checks on the text an agent is about
|
|
5
|
+
to write (PreToolUse) or just wrote (PostToolUse) and either blocks the write or
|
|
6
|
+
hands the model a structured feedback blob so the loop self-corrects without a
|
|
7
|
+
human round-trip.
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
AI coding agents write files directly. They introduce defect classes that
|
|
12
|
+
traditional linters and CI were not built to catch:
|
|
13
|
+
|
|
14
|
+
- **Valid-but-wrong CJK** -- a real but wrong kanji/hanzi/hangul (mojihen's
|
|
15
|
+
domain; grep and unit tests pass it as false-green).
|
|
16
|
+
- **Bidi / invisible Unicode** -- Trojan-Source bidi overrides and invisible
|
|
17
|
+
characters smuggled into source identifiers.
|
|
18
|
+
|
|
19
|
+
Both have standalone CLIs that run in CI. What is missing is a single hook at
|
|
20
|
+
the agent write boundary that (a) speaks the agents' hook protocols, (b) applies
|
|
21
|
+
one severity-to-action policy across checks, and (c) returns a model-readable
|
|
22
|
+
feedback blob so the agent rewrites itself.
|
|
23
|
+
|
|
24
|
+
## Positioning (honest)
|
|
25
|
+
|
|
26
|
+
agentgate is not a new category -- Claude Code and Codex already expose hook
|
|
27
|
+
frameworks. agentgate is the packaged, cross-agent gate that bundles
|
|
28
|
+
AI-write-specific checks, normalizes the two agents' payloads, centralizes
|
|
29
|
+
block/warn policy, and ships an open check registry so the set grows without
|
|
30
|
+
forking. The ecosystem value is the gate + registry standard, plus composing the
|
|
31
|
+
sibling engine mojihen, not any single linter.
|
|
32
|
+
|
|
33
|
+
## Coverage limits
|
|
34
|
+
|
|
35
|
+
agentgate only sees writes that flow through a hooked tool call. It does NOT see,
|
|
36
|
+
and makes no claim about:
|
|
37
|
+
|
|
38
|
+
- Files written by shell commands the agent runs (`echo >`, `sed -i`, codegen).
|
|
39
|
+
- Pre-existing files, generated artifacts, or out-of-band edits.
|
|
40
|
+
- Editor/IDE agents that do not emit the supported hook payloads.
|
|
41
|
+
- Codex tool paths other than `apply_patch` (best-effort; fail-open otherwise).
|
|
42
|
+
- Anything a PostToolUse hook is asked to undo -- it cannot roll back a completed
|
|
43
|
+
write, only report it back to the model.
|
|
44
|
+
|
|
45
|
+
## M1 built-in checks
|
|
46
|
+
|
|
47
|
+
### unicode (stdlib, always available)
|
|
48
|
+
|
|
49
|
+
- **AG-BIDI** (high, always block): bidi control characters U+202A-U+202E,
|
|
50
|
+
U+2066-U+2069. These are the Trojan-Source vectors with essentially no
|
|
51
|
+
legitimate use in source files.
|
|
52
|
+
- **AG-INVIS** (high, code context only): invisible chars (U+200B zero-width
|
|
53
|
+
space, U+2060 word joiner, U+FEFF stray BOM, U+00AD soft hyphen) flagged only
|
|
54
|
+
when the file has a code extension AND the char is inside an identifier/string
|
|
55
|
+
run. U+200C/U+200D (ZWNJ/ZWJ) and U+200E/U+200F (LRM/RLM) are NOT flagged
|
|
56
|
+
by default -- they are legitimate in Arabic/Persian/Indic text and emoji ZWJ
|
|
57
|
+
sequences. Strict mode (`unicode.strict_zerowidth = true`) adds ZWNJ/ZWJ only
|
|
58
|
+
inside ASCII-identifier runs.
|
|
59
|
+
- **AG-HOMO** (medium, opt-in): Latin-looking Cyrillic/Greek codepoints inside
|
|
60
|
+
an otherwise-ASCII identifier. Off by default.
|
|
61
|
+
|
|
62
|
+
### cjk (requires mojihen extra)
|
|
63
|
+
|
|
64
|
+
Embeds `mojihen.detect.run_detectors` to catch known LLM CJK corruption: a
|
|
65
|
+
real but wrong kanji/hanzi that grep and unit tests pass as false-green (rule
|
|
66
|
+
MH001 and others). Disabled by default so the stdlib-only core installs and runs
|
|
67
|
+
out of the box.
|
|
68
|
+
|
|
69
|
+
## Install
|
|
70
|
+
|
|
71
|
+
Core (stdlib-only, unicode check):
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
pip install agent-write-gate
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
With CJK check (requires mojihen):
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
pip install agent-write-gate[cjk]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Then enable in config:
|
|
84
|
+
|
|
85
|
+
```toml
|
|
86
|
+
# agentgate.toml
|
|
87
|
+
[checks]
|
|
88
|
+
cjk = true
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## CLI
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
# Primary: agent hook entrypoint (pipe JSON from agent hook system)
|
|
95
|
+
agentgate hook --stdin
|
|
96
|
+
|
|
97
|
+
# Scan files (CI / manual audit)
|
|
98
|
+
agentgate scan src/ --format tty|json|sarif
|
|
99
|
+
|
|
100
|
+
# List checks and their status
|
|
101
|
+
agentgate checks
|
|
102
|
+
|
|
103
|
+
# Version
|
|
104
|
+
agentgate --version
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Exit codes:
|
|
108
|
+
- `hook`: 0 = allow; 2 = block (deny in Pre / feedback in Post) or error.
|
|
109
|
+
- `scan`: 0 = no blocking findings; 1 = blocking findings; 2 = error.
|
|
110
|
+
|
|
111
|
+
## Hook setup: Claude Code
|
|
112
|
+
|
|
113
|
+
Add to `.claude/settings.json`:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"hooks": {
|
|
118
|
+
"PreToolUse": [
|
|
119
|
+
{
|
|
120
|
+
"matcher": "Write|Edit",
|
|
121
|
+
"hooks": [{"type": "command", "command": "agentgate hook --stdin"}]
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**PreToolUse** (exit 2) denies the tool call -- the write never happens.
|
|
129
|
+
**PostToolUse** (exit 2) surfaces feedback to the model after the write.
|
|
130
|
+
Only PreToolUse provides true prevention. See `hooks/claude-code.md`.
|
|
131
|
+
|
|
132
|
+
## Hook setup: Codex
|
|
133
|
+
|
|
134
|
+
Only `apply_patch` is supported (Codex's primary write tool):
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"hooks": {
|
|
139
|
+
"PreToolUse": [
|
|
140
|
+
{
|
|
141
|
+
"matcher": "apply_patch",
|
|
142
|
+
"hooks": [{"type": "command", "command": "agentgate hook --stdin"}]
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
See `hooks/codex.md` for PostToolUse setup and coverage limits.
|
|
150
|
+
|
|
151
|
+
## pre-commit
|
|
152
|
+
|
|
153
|
+
```yaml
|
|
154
|
+
# .pre-commit-config.yaml
|
|
155
|
+
repos:
|
|
156
|
+
- repo: https://github.com/hryoma1217/agentgate
|
|
157
|
+
rev: v0.1.0
|
|
158
|
+
hooks:
|
|
159
|
+
- id: agentgate
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The bidi / invisible-Unicode checks work out of the box. The CJK corruption
|
|
163
|
+
check is **off by default**; if you enable it (`[checks.cjk] enabled = true`), the
|
|
164
|
+
hook also needs `mojihen` in pre-commit's isolated env — add it via
|
|
165
|
+
`additional_dependencies`:
|
|
166
|
+
|
|
167
|
+
```yaml
|
|
168
|
+
- id: agentgate
|
|
169
|
+
additional_dependencies: ["agent-write-gate[cjk]"]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Configuration
|
|
173
|
+
|
|
174
|
+
`agentgate.toml` or `[tool.agentgate]` in `pyproject.toml`. Falls back to
|
|
175
|
+
defaults when no config file is found.
|
|
176
|
+
|
|
177
|
+
```toml
|
|
178
|
+
# Unicode checks are ON by default; the CJK check is OFF by default.
|
|
179
|
+
# Enable CJK only if you installed the `agent-write-gate[cjk]` extra.
|
|
180
|
+
[checks.cjk]
|
|
181
|
+
enabled = false
|
|
182
|
+
min_confidence = "high"
|
|
183
|
+
|
|
184
|
+
[checks.unicode]
|
|
185
|
+
enabled = true
|
|
186
|
+
homoglyph = false
|
|
187
|
+
strict_zerowidth = false
|
|
188
|
+
allow_bidi_suppression = false
|
|
189
|
+
code_extensions = [
|
|
190
|
+
".py", ".js", ".ts", ".go", ".rs", ".java",
|
|
191
|
+
".c", ".cpp", ".rb", ".php", ".sh", ".sql"
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[policy]
|
|
195
|
+
high = "block"
|
|
196
|
+
medium = "warn"
|
|
197
|
+
low = "ignore"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Suppression
|
|
201
|
+
|
|
202
|
+
Rule-specific only: `agentgate: ignore[AG-INVIS]` on the offending line.
|
|
203
|
+
**There is no bare `agentgate: ignore`** -- that would let a model launder
|
|
204
|
+
violations. AG-BIDI is not suppressible unless `allow_bidi_suppression = true`.
|
|
205
|
+
|
|
206
|
+
## Model-readable block report
|
|
207
|
+
|
|
208
|
+
When a write is blocked, stderr looks like:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
agentgate: BLOCKED -- 2 issue(s) to fix before this write
|
|
212
|
+
|
|
213
|
+
app.py:3:18 cjk/MH001 HIGH '闾' -> likely: 閾
|
|
214
|
+
'闾' is a known LLM corruption (likely intended: 閾) ...
|
|
215
|
+
app.py:5:1 unicode/AG-BIDI HIGH U+202E RIGHT-TO-LEFT OVERRIDE
|
|
216
|
+
Remove the bidi control char; it visually reorders source.
|
|
217
|
+
|
|
218
|
+
Fix these and re-emit.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The model sees this as a structured remediation signal and issues a corrective
|
|
222
|
+
write without human intervention.
|
|
223
|
+
|
|
224
|
+
## Relationship to mojihen
|
|
225
|
+
|
|
226
|
+
mojihen is the CJK engine (its own PyPI package, independently useful).
|
|
227
|
+
agentgate is the cross-agent gate that composes it (optional extra
|
|
228
|
+
`agent-write-gate[cjk]`) with the stdlib Unicode-safety check, under one policy and
|
|
229
|
+
one model-readable feedback contract. Two focused packages; the gate + open
|
|
230
|
+
registry is the ecosystem layer.
|
|
231
|
+
|
|
232
|
+
## Open registry
|
|
233
|
+
|
|
234
|
+
Third-party checks can be registered:
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from agentgate.registry import register
|
|
238
|
+
|
|
239
|
+
def my_check(event, cfg):
|
|
240
|
+
# event: WriteEvent, cfg: GateConfig
|
|
241
|
+
# return List[Issue]
|
|
242
|
+
return []
|
|
243
|
+
|
|
244
|
+
register("my-check", my_check)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## License
|
|
248
|
+
|
|
249
|
+
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agent-write-gate"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Agent-hook safety gate for AI-written code -- blocks bidi/invisible Unicode and CJK corruption at the write boundary"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
dependencies = ["tomli>=1.1.0; python_version < '3.11'"]
|
|
13
|
+
keywords = ["agent", "hook", "safety", "unicode", "cjk", "llm", "claude-code", "codex", "pre-commit"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
25
|
+
"Topic :: Security",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
agentgate = "agentgate.cli:main"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
cjk = ["mojihen>=0.1"]
|
|
33
|
+
dev = ["pytest"]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|