agentcheckup 0.4.2__tar.gz → 0.4.3__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.
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/ISSUE_TEMPLATE/config.yml +2 -2
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/workflows/publish.yml +1 -1
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/CONTRIBUTING.md +1 -1
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/LICENSE +1 -1
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/PKG-INFO +16 -7
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/README.md +11 -2
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/README.zh-CN.md +8 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/SECURITY.md +1 -1
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/action.yml +1 -1
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/docs/github-action.md +6 -6
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/pyproject.toml +5 -5
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/conflicts.py +28 -3
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/report.py +3 -3
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/test_conflicts.py +37 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.gitattributes +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/ISSUE_TEMPLATE/rule_request.yml +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/pull_request_template.md +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/workflows/action-selftest.yml +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.github/workflows/ci.yml +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/.gitignore +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/CHANGELOG.md +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/CODE_OF_CONDUCT.md +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/Makefile +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/conftest.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/docs/rules.md +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/scripts/bootstrap.ps1 +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/scripts/bootstrap.sh +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/__init__.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/__main__.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/cli.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/discovery.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/engine.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/loader.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/models.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/__init__.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/base.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/config_rules.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/docs.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/injection.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/naming.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/safety.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/rules/schema.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/src/agentcheckup/tokens.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/fixtures/bad_tools.json +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/fixtures/ci_config.json +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/fixtures/claude_desktop_config.json +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/fixtures/good_tools.json +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/fixtures/mock_server.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/test_cli.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/test_discovery.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/test_registry.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/test_rules.py +0 -0
- {agentcheckup-0.4.2 → agentcheckup-0.4.3}/tests/test_scoring.py +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
blank_issues_enabled: false
|
|
2
2
|
contact_links:
|
|
3
3
|
- name: Question or idea
|
|
4
|
-
url: https://github.com/
|
|
4
|
+
url: https://github.com/jiaqinq/agentcheckup/discussions
|
|
5
5
|
about: For open-ended discussion, use Discussions instead of an issue.
|
|
6
6
|
- name: Security vulnerability
|
|
7
|
-
url: https://github.com/
|
|
7
|
+
url: https://github.com/jiaqinq/agentcheckup/security/advisories/new
|
|
8
8
|
about: Please report security issues privately, not in a public issue.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agentcheckup
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Diagnose your agent setup: tool conflicts, risky config, context budget.
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Issues, https://github.com/
|
|
7
|
-
Project-URL: Changelog, https://github.com/
|
|
8
|
-
Author:
|
|
5
|
+
Project-URL: Homepage, https://github.com/jiaqinq/agentcheckup
|
|
6
|
+
Project-URL: Issues, https://github.com/jiaqinq/agentcheckup/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/jiaqinq/agentcheckup/blob/main/CHANGELOG.md
|
|
8
|
+
Author: jiaqinq
|
|
9
9
|
License: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Keywords: agents,ai,cli,linter,mcp,model-context-protocol,security
|
|
@@ -30,7 +30,7 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
|
|
31
31
|
> Diagnose your agent setup before your agent does.
|
|
32
32
|
|
|
33
|
-
[](https://github.com/jiaqinq/agentcheckup/actions/workflows/ci.yml)
|
|
34
34
|
[](https://pypi.org/project/agentcheckup/)
|
|
35
35
|
[](https://pypi.org/project/agentcheckup/)
|
|
36
36
|
[](LICENSE)
|
|
@@ -149,7 +149,7 @@ The fastest way to keep a manifest from regressing, and the version you pin is
|
|
|
149
149
|
the version you run — the action installs from its own checkout.
|
|
150
150
|
|
|
151
151
|
```yaml
|
|
152
|
-
- uses:
|
|
152
|
+
- uses: jiaqinq/agentcheckup@v0.4.3
|
|
153
153
|
with:
|
|
154
154
|
config: .mcp.json
|
|
155
155
|
fail-on: warning
|
|
@@ -193,6 +193,11 @@ Each tool pair across servers is scored on two signals:
|
|
|
193
193
|
- **name overlap** — normalised token Jaccard (`read_files` ≡ `read_file`)
|
|
194
194
|
- **description overlap** — token Jaccard over stopword-stripped, plural-stemmed words
|
|
195
195
|
|
|
196
|
+
Chinese is tokenised as character bigrams (`读取文件` → `读取`, `取文`, `文件`) rather
|
|
197
|
+
than by a segmenter, because a segmenter is a dependency. It is cruder than a real
|
|
198
|
+
word split, but without it every Chinese description produced an empty token set
|
|
199
|
+
and two Chinese tools could never be compared at all.
|
|
200
|
+
|
|
196
201
|
A pair is flagged when the descriptions overlap ≥ 65% **and** the names share a
|
|
197
202
|
head noun, or when the blended score clears 0.55. The shared-noun requirement is
|
|
198
203
|
what keeps `search_repositories` and `search_documents` apart — without it the
|
|
@@ -251,6 +256,10 @@ rule. A report nobody can read is a report nobody acts on.
|
|
|
251
256
|
- Not an MCP protocol validator. It checks quality and safety, not conformance —
|
|
252
257
|
the official `modelcontextprotocol/conformance` suite does that.
|
|
253
258
|
|
|
259
|
+
## Further reading
|
|
260
|
+
|
|
261
|
+
- [多个 MCP Server 一起使用时,如何检测工具冲突?](https://juejin.cn/post/7704995965740580904) — the design story, in Chinese: why the scope changed from a single-server linter to cross-server conflicts, and how the scoring was rebuilt after it graded the official servers 0/100.
|
|
262
|
+
|
|
254
263
|
## Contributing
|
|
255
264
|
|
|
256
265
|
Adding a rule takes about ten minutes and one small file — see
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Diagnose your agent setup before your agent does.
|
|
4
4
|
|
|
5
|
-
[](https://github.com/jiaqinq/agentcheckup/actions/workflows/ci.yml)
|
|
6
6
|
[](https://pypi.org/project/agentcheckup/)
|
|
7
7
|
[](https://pypi.org/project/agentcheckup/)
|
|
8
8
|
[](LICENSE)
|
|
@@ -121,7 +121,7 @@ The fastest way to keep a manifest from regressing, and the version you pin is
|
|
|
121
121
|
the version you run — the action installs from its own checkout.
|
|
122
122
|
|
|
123
123
|
```yaml
|
|
124
|
-
- uses:
|
|
124
|
+
- uses: jiaqinq/agentcheckup@v0.4.3
|
|
125
125
|
with:
|
|
126
126
|
config: .mcp.json
|
|
127
127
|
fail-on: warning
|
|
@@ -165,6 +165,11 @@ Each tool pair across servers is scored on two signals:
|
|
|
165
165
|
- **name overlap** — normalised token Jaccard (`read_files` ≡ `read_file`)
|
|
166
166
|
- **description overlap** — token Jaccard over stopword-stripped, plural-stemmed words
|
|
167
167
|
|
|
168
|
+
Chinese is tokenised as character bigrams (`读取文件` → `读取`, `取文`, `文件`) rather
|
|
169
|
+
than by a segmenter, because a segmenter is a dependency. It is cruder than a real
|
|
170
|
+
word split, but without it every Chinese description produced an empty token set
|
|
171
|
+
and two Chinese tools could never be compared at all.
|
|
172
|
+
|
|
168
173
|
A pair is flagged when the descriptions overlap ≥ 65% **and** the names share a
|
|
169
174
|
head noun, or when the blended score clears 0.55. The shared-noun requirement is
|
|
170
175
|
what keeps `search_repositories` and `search_documents` apart — without it the
|
|
@@ -223,6 +228,10 @@ rule. A report nobody can read is a report nobody acts on.
|
|
|
223
228
|
- Not an MCP protocol validator. It checks quality and safety, not conformance —
|
|
224
229
|
the official `modelcontextprotocol/conformance` suite does that.
|
|
225
230
|
|
|
231
|
+
## Further reading
|
|
232
|
+
|
|
233
|
+
- [多个 MCP Server 一起使用时,如何检测工具冲突?](https://juejin.cn/post/7704995965740580904) — the design story, in Chinese: why the scope changed from a single-server linter to cross-server conflicts, and how the scoring was rebuilt after it graded the official servers 0/100.
|
|
234
|
+
|
|
226
235
|
## Contributing
|
|
227
236
|
|
|
228
237
|
Adding a rule takes about ten minutes and one small file — see
|
|
@@ -118,6 +118,10 @@ agentcheckup rules # 列出全部规则
|
|
|
118
118
|
- **名字重叠**:归一化后的 token Jaccard(`read_files` ≡ `read_file`)
|
|
119
119
|
- **描述重叠**:去停用词、粗词干化之后的 token Jaccard
|
|
120
120
|
|
|
121
|
+
中文按**字符二元组**切分(`读取文件` → `读取`、`取文`、`文件`),没有引入分词器——
|
|
122
|
+
分词器就是依赖。这比真正的分词粗,但没有它的时候中文描述会得到空集合,
|
|
123
|
+
两个中文工具根本无法比较。
|
|
124
|
+
|
|
121
125
|
判定条件:描述重叠 ≥ 65% **且** 名字共享中心词,或加权分 ≥ 0.55。
|
|
122
126
|
共享中心词这个约束是关键——没有它,`search_repositories` 和 `search_documents`
|
|
123
127
|
会因为都含 "search" 被误报,而**充满噪音的报告比没有报告更糟**。
|
|
@@ -165,6 +169,10 @@ agentcheckup rules # 列出全部规则
|
|
|
165
169
|
- 不是运行时防护。它不在 agent 会话里运行。
|
|
166
170
|
- 不是 MCP 协议校验器。协议一致性由官方 `modelcontextprotocol/conformance` 负责。
|
|
167
171
|
|
|
172
|
+
## 相关文章
|
|
173
|
+
|
|
174
|
+
- [多个 MCP Server 一起使用时,如何检测工具冲突?](https://juejin.cn/post/7704995965740580904) —— 设计复盘:为什么从单 server linter 改成跨 server 冲突检测,以及评分把官方 server 打成 0 分之后怎么重做。
|
|
175
|
+
|
|
168
176
|
## 贡献
|
|
169
177
|
|
|
170
178
|
加一条规则大约十分钟、一个文件,见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
@@ -14,7 +14,7 @@ Nothing leaves your machine.
|
|
|
14
14
|
## Reporting a vulnerability
|
|
15
15
|
|
|
16
16
|
Use GitHub's private advisory flow:
|
|
17
|
-
`https://github.com/
|
|
17
|
+
`https://github.com/jiaqinq/agentcheckup/security/advisories/new`
|
|
18
18
|
|
|
19
19
|
Please do not open a public issue for a vulnerability. Expect an initial response
|
|
20
20
|
within 7 days.
|
|
@@ -13,7 +13,7 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
15
|
- uses: actions/checkout@v4
|
|
16
|
-
- uses:
|
|
16
|
+
- uses: jiaqinq/agentcheckup@main
|
|
17
17
|
with:
|
|
18
18
|
config: .mcp.json
|
|
19
19
|
fail-on: warning
|
|
@@ -45,7 +45,7 @@ Outputs are published even when the gate fails, so you can gate on score without
|
|
|
45
45
|
parsing the log:
|
|
46
46
|
|
|
47
47
|
```yaml
|
|
48
|
-
- uses:
|
|
48
|
+
- uses: jiaqinq/agentcheckup@main
|
|
49
49
|
id: doctor
|
|
50
50
|
with:
|
|
51
51
|
config: .mcp.json
|
|
@@ -64,7 +64,7 @@ permissions:
|
|
|
64
64
|
|
|
65
65
|
steps:
|
|
66
66
|
- uses: actions/checkout@v4
|
|
67
|
-
- uses:
|
|
67
|
+
- uses: jiaqinq/agentcheckup@main
|
|
68
68
|
with:
|
|
69
69
|
config: .mcp.json
|
|
70
70
|
sarif-file: agentcheckup.sarif
|
|
@@ -87,7 +87,7 @@ for locally. On a fresh runner that usually finds nothing, and agentcheckup exit
|
|
|
87
87
|
For CI, pass the config explicitly:
|
|
88
88
|
|
|
89
89
|
```yaml
|
|
90
|
-
- uses:
|
|
90
|
+
- uses: jiaqinq/agentcheckup@main
|
|
91
91
|
with:
|
|
92
92
|
config: |
|
|
93
93
|
.mcp.json
|
|
@@ -99,7 +99,7 @@ For CI, pass the config explicitly:
|
|
|
99
99
|
Spawning every MCP server takes time. If you only need the config checks:
|
|
100
100
|
|
|
101
101
|
```yaml
|
|
102
|
-
- uses:
|
|
102
|
+
- uses: jiaqinq/agentcheckup@main
|
|
103
103
|
with:
|
|
104
104
|
config: .mcp.json
|
|
105
105
|
args: --no-spawn
|
|
@@ -113,5 +113,5 @@ are skipped too. It is fast and useful, but it is not the full check.
|
|
|
113
113
|
`@main` tracks the branch. For reproducible CI, pin a tag or a commit SHA:
|
|
114
114
|
|
|
115
115
|
```yaml
|
|
116
|
-
- uses:
|
|
116
|
+
- uses: jiaqinq/agentcheckup@v0.3.0
|
|
117
117
|
```
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentcheckup"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.3"
|
|
8
8
|
description = "Diagnose your agent setup: tool conflicts, risky config, context budget."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
license = { text = "MIT" }
|
|
12
|
-
authors = [{ name = "
|
|
12
|
+
authors = [{ name = "jiaqinq" }]
|
|
13
13
|
keywords = ["mcp", "model-context-protocol", "agents", "ai", "linter", "security", "cli"]
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Development Status :: 3 - Alpha",
|
|
@@ -33,9 +33,9 @@ dev = ["pytest>=8", "ruff>=0.6"]
|
|
|
33
33
|
agentcheckup = "agentcheckup.cli:main"
|
|
34
34
|
|
|
35
35
|
[project.urls]
|
|
36
|
-
Homepage = "https://github.com/
|
|
37
|
-
Issues = "https://github.com/
|
|
38
|
-
Changelog = "https://github.com/
|
|
36
|
+
Homepage = "https://github.com/jiaqinq/agentcheckup"
|
|
37
|
+
Issues = "https://github.com/jiaqinq/agentcheckup/issues"
|
|
38
|
+
Changelog = "https://github.com/jiaqinq/agentcheckup/blob/main/CHANGELOG.md"
|
|
39
39
|
|
|
40
40
|
[tool.hatch.build.targets.wheel]
|
|
41
41
|
packages = ["src/agentcheckup"]
|
|
@@ -42,6 +42,10 @@ STOPWORDS = frozenset(
|
|
|
42
42
|
|
|
43
43
|
WORD = re.compile(r"[a-z0-9]+")
|
|
44
44
|
|
|
45
|
+
#: CJK ideographs, extension A included. Matched per character because Chinese
|
|
46
|
+
#: has no word delimiters and a real segmenter would be a dependency.
|
|
47
|
+
CJK = re.compile(r"[\u3400-\u4dbf\u4e00-\u9fff]+")
|
|
48
|
+
|
|
45
49
|
|
|
46
50
|
@dataclass(frozen=True)
|
|
47
51
|
class ToolRef:
|
|
@@ -94,13 +98,33 @@ def _stem(word: str) -> str:
|
|
|
94
98
|
return word
|
|
95
99
|
|
|
96
100
|
|
|
101
|
+
def _cjk_tokens(text: str) -> set[str]:
|
|
102
|
+
"""Character bigrams over every CJK run.
|
|
103
|
+
|
|
104
|
+
Chinese has no spaces, so ``WORD`` returns nothing and two Chinese tools
|
|
105
|
+
would look like two empty sets — silently, which is the worst outcome. A real
|
|
106
|
+
segmenter is a dependency; character bigrams are the standard cheap
|
|
107
|
+
substitute: 读取文件 -> 读取, 取文, 文件.
|
|
108
|
+
|
|
109
|
+
A single-character run is kept whole, so 读 still matches 读.
|
|
110
|
+
"""
|
|
111
|
+
out: set[str] = set()
|
|
112
|
+
for run in CJK.findall(text):
|
|
113
|
+
if len(run) == 1:
|
|
114
|
+
out.add(run)
|
|
115
|
+
else:
|
|
116
|
+
out.update(run[i : i + 2] for i in range(len(run) - 1))
|
|
117
|
+
return out
|
|
118
|
+
|
|
119
|
+
|
|
97
120
|
def tokens(text: str) -> set[str]:
|
|
98
|
-
"""Lowercase word set, stopwords removed, crude plural stemming."""
|
|
99
|
-
|
|
121
|
+
"""Lowercase word set, stopwords removed, crude plural stemming, plus CJK."""
|
|
122
|
+
latin = {
|
|
100
123
|
_stem(w)
|
|
101
124
|
for w in WORD.findall(text.lower())
|
|
102
125
|
if w not in STOPWORDS and len(w) > 1
|
|
103
126
|
}
|
|
127
|
+
return latin | _cjk_tokens(text)
|
|
104
128
|
|
|
105
129
|
|
|
106
130
|
def jaccard(a: set[str], b: set[str]) -> float:
|
|
@@ -111,7 +135,8 @@ def jaccard(a: set[str], b: set[str]) -> float:
|
|
|
111
135
|
|
|
112
136
|
|
|
113
137
|
def name_tokens(name: str) -> set[str]:
|
|
114
|
-
|
|
138
|
+
latin = {_stem(w) for w in WORD.findall(name.lower()) if len(w) > 1}
|
|
139
|
+
return latin | _cjk_tokens(name)
|
|
115
140
|
|
|
116
141
|
|
|
117
142
|
def similarity(a: ToolRef, b: ToolRef) -> float:
|
|
@@ -10,7 +10,7 @@ from . import rules as _rules
|
|
|
10
10
|
from .engine import Report
|
|
11
11
|
from .models import Finding, Severity
|
|
12
12
|
|
|
13
|
-
__version__ = "0.4.
|
|
13
|
+
__version__ = "0.4.3"
|
|
14
14
|
|
|
15
15
|
SARIF_LEVEL = {
|
|
16
16
|
Severity.ERROR: "error",
|
|
@@ -195,7 +195,7 @@ def render_text(report: Report, verbose: bool = False) -> str:
|
|
|
195
195
|
lines.extend(_nudge_lines(nudges))
|
|
196
196
|
|
|
197
197
|
lines.append("")
|
|
198
|
-
lines.append(" Rule docs: https://github.com/
|
|
198
|
+
lines.append(" Rule docs: https://github.com/jiaqinq/agentcheckup#rules")
|
|
199
199
|
return "\n".join(lines)
|
|
200
200
|
|
|
201
201
|
|
|
@@ -246,7 +246,7 @@ def render_sarif(report: Report) -> str:
|
|
|
246
246
|
"driver": {
|
|
247
247
|
"name": "agentcheckup",
|
|
248
248
|
"version": __version__,
|
|
249
|
-
"informationUri": "https://github.com/
|
|
249
|
+
"informationUri": "https://github.com/jiaqinq/agentcheckup",
|
|
250
250
|
"rules": _rule_metadata(),
|
|
251
251
|
}
|
|
252
252
|
},
|
|
@@ -128,3 +128,40 @@ def test_audit_tokens_sum_across_servers():
|
|
|
128
128
|
tools = {"a": [tool("alpha_tool")], "b": [tool("beta_tool")]}
|
|
129
129
|
report = lint_audit(servers, tools)
|
|
130
130
|
assert report.tokens > 0
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# --------------------------------------------------------------------------- #
|
|
134
|
+
# CJK support
|
|
135
|
+
# --------------------------------------------------------------------------- #
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def test_cjk_runs_become_character_bigrams():
|
|
139
|
+
assert tokens("读取文件") == {"读取", "取文", "文件"}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_single_cjk_character_is_kept_whole():
|
|
143
|
+
assert tokens("读") == {"读"}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_cjk_and_latin_mix():
|
|
147
|
+
got = tokens("read 文件")
|
|
148
|
+
assert "read" in got
|
|
149
|
+
assert "文件" in got
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_chinese_near_duplicates_are_flagged():
|
|
153
|
+
"""Before CJK support this pair produced two empty token sets and no finding."""
|
|
154
|
+
a = ref("文件服务", "读取文件", "读取指定路径的文件内容并返回文本")
|
|
155
|
+
b = ref("文档服务", "读取文档", "读取指定路径的文件内容并返回字符串")
|
|
156
|
+
assert "AGT203" in {c.rule for c in detect_conflicts([a, b])}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_chinese_unrelated_tools_are_not_flagged():
|
|
160
|
+
a = ref("文件服务", "读取文件", "读取指定路径的文件内容并返回文本")
|
|
161
|
+
b = ref("文件服务", "删除文件", "删除指定路径的文件")
|
|
162
|
+
assert detect_conflicts([a, b]) == []
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def test_english_scores_are_unchanged_by_cjk_support():
|
|
166
|
+
"""The CJK path must not touch Latin tokenisation."""
|
|
167
|
+
assert tokens("Read a file") == {"read", "file"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|