Skip to content

Commit abff94c

Browse files
author
loong10k
committed
chore: README MCP 章节 + CI 装 mcp 依赖 + 全仓 ruff 债务清零
- README/zh:修正过期「MCP 未发布」表行,新增镜像 MCP 章节(parity 5/5) - skills-check.yml:unittest 前 pip install requirements.txt(MCP 测试不 skip) - .gitignore:out/ - tasks.md:组 1-6 勾选 24/29,3.1 更正为根 requirements.txt + CI 安装 - 全仓 ruff 41 项清零(PLW1510 check=False / BLE001 fail-open noqa / EXE 位 / RUF059 改名 / SIM115-402 / TRY004 保型 noqa)—— 提交门禁跑全仓 ruff check .,债务不清则任何提交都过不了
1 parent 27c813c commit abff94c

25 files changed

Lines changed: 129 additions & 87 deletions

‎.github/workflows/skills-check.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ jobs:
1515
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
1616
with:
1717
python-version: "3.12"
18+
- name: Install requirements (mcp SDK so MCP server tests run, not skip)
19+
run: python3 -m pip install --disable-pip-version-check -r requirements.txt
1820
- name: Verify vendored skills match the lockfile digests
1921
run: python3 scripts/vendor/skill_vendor.py check --offline
2022
- name: Verify lockfile pins still match upstream refs and content

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ build/
1919
dist/
2020
htmlcov/
2121
Thumbs.db
22+
# codeguard 失败日志落盘目录
23+
out/

‎README.md‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ AI code that passes lint on first try
7070
| Current version | `0.6.7` |
7171
| ZCode manifest | `.zcode-plugin/plugin.json` |
7272
| Codex manifest | `.codex-plugin/plugin.json` |
73-
| MCP server | Not published until the SDK-backed protocol implementation is ready; use the CLI and hooks |
73+
| MCP server | Published: stdio server via the official SDK (`check_code_style` / `auto_fix` / `list_languages`); see Quick start |
7474
| Primary language | Python 3.10+ (hooks), YAML/JSON (config) |
7575
| License | Apache-2.0 |
7676

@@ -199,6 +199,25 @@ When this plugin is active, you do **not** need to do anything manually:
199199
- When the user says "commit", you will receive a final all-linters-must-pass gate check.
200200
- At session end, you will see a summary of which lints passed/failed.
201201

202+
### MCP server
203+
204+
`run_check.py --mcp` starts a stdio MCP server (official `mcp` SDK; install
205+
dependencies with `pip install -r requirements.txt`) exposing three tools:
206+
207+
| Tool | Purpose |
208+
|---|---|
209+
| `check_code_style` | Run lint and return a per-language envelope with `stderr_path` and `log_path` |
210+
| `auto_fix` | Run the formatter chain, then re-run lint and embed the check envelope |
211+
| `list_languages` | List supported language ids and display names (no internal commands) |
212+
213+
```bash
214+
python3 scripts/run_check.py --mcp .
215+
```
216+
217+
Failed runs write the full combined output to `<project>/out/.codeguard-last.log`
218+
(the same path appears in the tool envelope and the CLI summary line; suppress
219+
with `--quiet`).
220+
202221
## Configuration
203222

204223
User config in `~/.zcode/settings.local.yaml` (ZCode) or equivalent for other hosts:

‎README.zh-CN.md‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ AI 一次写出就过 lint 的代码
7070
| 当前版本 | `0.6.7` |
7171
| ZCode manifest | `.zcode-plugin/plugin.json` |
7272
| Codex manifest | `.codex-plugin/plugin.json` |
73-
| MCP 服务 | SDK 协议实现完成前不随清单发布;当前使用 CLI 与 Hooks |
73+
| MCP 服务 | 已发布:官方 SDK stdio 服务(`check_code_style` / `auto_fix` / `list_languages`);见快速开始 |
7474
| 主要语言 | Python 3.10+(钩子)、YAML/JSON(配置) |
7575
| 协议 | Apache-2.0 |
7676

@@ -184,6 +184,24 @@ ln -s $PWD ~/.kimi/plugins/partme-codeguard-plugin
184184
- 用户说「commit」时,你会受到「所有 linter 必须通过」的最后门禁
185185
- 会话结束时会看到本会话 lint 通过/失败的总结
186186

187+
### MCP 服务器
188+
189+
`run_check.py --mcp` 启动 stdio MCP 服务(官方 `mcp` SDK;先用
190+
`pip install -r requirements.txt` 安装依赖),暴露三个工具:
191+
192+
| 工具 | 用途 |
193+
|---|---|
194+
| `check_code_style` | 跑 lint,返回逐语言信封与 `stderr_path`、`log_path` |
195+
| `auto_fix` | 先跑 formatter 链再复检 lint(嵌入 check 信封) |
196+
| `list_languages` | 列出语言 id 与显示名(不含内部命令) |
197+
198+
```bash
199+
python3 scripts/run_check.py --mcp .
200+
```
201+
202+
失败时完整输出落盘到 `<项目根>/out/.codeguard-last.log`(与工具信封及 CLI
203+
摘要行里的路径一致;`--quiet` 可关闭)。
204+
187205
## 配置
188206

189207
`~/.zcode/settings.local.yaml`(ZCode)或各平台对应文件:

‎hooks/env_check.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
3. 输出一段 AGENTS.md 风格的提示,让 AI 知道自己在一个被 codeguard 管理的项目里
88
"""
99
import os
10-
import shutil
1110
import subprocess
1211
import sys
1312
from pathlib import Path
@@ -129,6 +128,6 @@ def main() -> int:
129128
sys.exit(main())
130129
except SystemExit:
131130
raise
132-
except Exception as exc: # 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
131+
except Exception as exc: # noqa: BLE001 — 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
133132
print(f"[codeguard] 内部错误已忽略(fail-open): {exc!r}", file=sys.stderr)
134133
sys.exit(0)

‎hooks/gate_lib.py‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
PLUGIN_ROOT = Path(__file__).resolve().parents[1] # hooks/ 的上级 = 插件根
1818
sys.path.insert(0, str(PLUGIN_ROOT / "scripts"))
1919

20-
from detect_lang import ( # noqa: E402
21-
LANG_COMMANDS, detect_languages, load_user_config, project_uses_linter, probe_toolchain,
20+
from detect_lang import (
21+
LANG_COMMANDS,
22+
detect_languages,
23+
probe_toolchain,
24+
project_uses_linter,
2225
)
2326

24-
2527
# === git 提交内容安全检查:绝不该进版本库的文件 ===
2628
# 目录(路径任一段落匹配即违规):依赖/虚拟环境/构建产物/IDE/缓存
2729
GUARD_EXCLUDE_DIRS = {
@@ -43,7 +45,7 @@ def _git(project_root: Path, *args: str) -> str | None:
4345
"""跑只读 git 命令;失败(非 git 仓/无 upstream 等)返回 None,由调用方降级"""
4446
try:
4547
proc = subprocess.run(
46-
["git", *args], cwd=project_root, capture_output=True, text=True, timeout=15
48+
["git", *args], cwd=project_root, capture_output=True, check=False, text=True, timeout=15
4749
)
4850
except (subprocess.TimeoutExpired, OSError, FileNotFoundError):
4951
return None
@@ -101,7 +103,8 @@ def format_safety_report(violations: list[tuple[str, str, str]]) -> str:
101103

102104

103105
def _gate_cache_path(project_root: Path) -> Path:
104-
import hashlib, tempfile
106+
import hashlib
107+
import tempfile
105108
key = hashlib.sha1(str(project_root.resolve()).encode()).hexdigest()[:12]
106109
return Path(tempfile.gettempdir()) / f"codeguard-gate-{os.getuid()}-{key}.json"
107110

@@ -191,7 +194,7 @@ def check(lang: str):
191194
return (lang, None, f"{lang} 项目未接入(缺 linter 配置文件),本次未验证")
192195
try:
193196
proc = subprocess.run(
194-
gate_cmd, cwd=project_root, capture_output=True, text=True, timeout=timeout
197+
gate_cmd, cwd=project_root, capture_output=True, check=False, text=True, timeout=timeout
195198
)
196199
except subprocess.TimeoutExpired:
197200
return (lang, None, f"{lang} 检查超时(>{timeout}s),本次未验证")
@@ -217,7 +220,7 @@ def check(lang: str):
217220
for r in results: # pool.map 保序,输出与语言表顺序一致
218221
if r is None:
219222
continue
220-
lang, failure, skip = r
223+
_, failure, skip = r
221224
if failure:
222225
failures.append(failure)
223226
if skip:

‎hooks/post_tool_lint.py‎

100755100644
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def is_ejs_template(file_path: str) -> bool:
133133

134134
def run(cmd: list[str], cwd: Path, timeout: int = 300) -> tuple[int, str, str]:
135135
try:
136-
proc = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout)
136+
proc = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout, check=False)
137137
return proc.returncode, proc.stdout, proc.stderr
138138
except subprocess.TimeoutExpired:
139139
return 124, "", f"timeout after {timeout}s"
@@ -293,6 +293,6 @@ def materialize(cmd: list[str]) -> list[str]:
293293
sys.exit(main())
294294
except SystemExit:
295295
raise
296-
except Exception as exc: # 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
296+
except Exception as exc: # noqa: BLE001 — 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
297297
print(f"[codeguard] 内部错误已忽略(fail-open): {exc!r}", file=sys.stderr)
298298
sys.exit(0)

‎hooks/pre_tool_git_guard.py‎

100644100755
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111
from __future__ import annotations
1212

1313
import json
14-
import subprocess
1514
import os
15+
import subprocess
1616
import sys
1717
from pathlib import Path
1818

1919
PLUGIN_ROOT = Path(__file__).resolve().parents[1]
2020
sys.path.insert(0, str(PLUGIN_ROOT / "scripts"))
2121
sys.path.insert(0, str(PLUGIN_ROOT / "hooks"))
2222

23-
from detect_lang import ensure_user_path, find_project_root, load_user_config # noqa: E402
24-
from gate_lib import ( # noqa: E402
23+
from detect_lang import ensure_user_path, load_user_config
24+
from gate_lib import (
2525
check_commit_safety,
2626
format_safety_report,
2727
gate_directive,
@@ -51,7 +51,7 @@ def _is_git_repo(p: Path) -> bool:
5151
try:
5252
proc = subprocess.run(
5353
["git", "-C", str(p), "rev-parse", "--git-dir"],
54-
capture_output=True, text=True, timeout=10,
54+
capture_output=True, check=False, text=True, timeout=10,
5555
)
5656
except (subprocess.TimeoutExpired, OSError):
5757
return False
@@ -113,7 +113,7 @@ def skip_gate_via_git_config(project_root: Path) -> bool:
113113
try:
114114
proc = subprocess.run(
115115
["git", "config", "--get", "codeguard.skipGate"],
116-
cwd=project_root, capture_output=True, text=True, timeout=10,
116+
cwd=project_root, capture_output=True, check=False, text=True, timeout=10,
117117
)
118118
except (subprocess.TimeoutExpired, OSError):
119119
return False
@@ -165,6 +165,6 @@ def main() -> int:
165165
sys.exit(main())
166166
except SystemExit:
167167
raise
168-
except Exception as exc: # 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
168+
except Exception as exc: # noqa: BLE001 — 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
169169
print(f"[codeguard] 内部错误已忽略(fail-open): {exc!r}", file=sys.stderr)
170170
sys.exit(0)

‎hooks/stop_summary.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@ def main() -> int:
5757
sys.exit(main())
5858
except SystemExit:
5959
raise
60-
except Exception as exc: # 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
60+
except Exception as exc: # noqa: BLE001 — 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
6161
print(f"[codeguard] 内部错误已忽略(fail-open): {exc!r}", file=sys.stderr)
6262
sys.exit(0)

‎hooks/user_prompt_validator.py‎

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,26 @@
1919
sys.path.insert(0, str(PLUGIN_ROOT / "scripts"))
2020
sys.path.insert(0, str(PLUGIN_ROOT / "hooks"))
2121

22-
from detect_lang import detect_languages, ensure_user_path, find_project_root, load_user_config # noqa: E402
23-
from gate_lib import ( # noqa: E402
22+
# 触发此钩子的关键词(中英)
23+
# 英文按词边界匹配(防止 pushed/deployment 误命中),中文子串即可。
24+
# 2026-09-22 实测回归:`我刚才 pushed 了`、`关于 deployment 策略的讨论`
25+
# 必须静默(子串匹配曾把它们当提交意图跑全仓 lint)。
26+
import re as _re
27+
28+
from detect_lang import (
29+
detect_languages,
30+
ensure_user_path,
31+
find_project_root,
32+
load_user_config,
33+
)
34+
from gate_lib import (
2435
check_commit_safety,
2536
format_safety_report,
2637
gate_directive,
2738
run_gate,
2839
summarize_failures,
2940
)
3041

31-
# 触发此钩子的关键词(中英)
32-
# 英文按词边界匹配(防止 pushed/deployment 误命中),中文子串即可。
33-
# 2026-09-22 实测回归:`我刚才 pushed 了`、`关于 deployment 策略的讨论`
34-
# 必须静默(子串匹配曾把它们当提交意图跑全仓 lint)。
35-
import re as _re
36-
3742
TRIGGER_PATTERNS = [
3843
"commit", "push", "deploy", "提交", "发布", "部署",
3944
]
@@ -178,6 +183,6 @@ def main() -> int:
178183
sys.exit(main())
179184
except SystemExit:
180185
raise
181-
except Exception as exc: # 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
186+
except Exception as exc: # noqa: BLE001 — 内部错误 fail-open:traceback 绝不进 AI 上下文/阻断工作流
182187
print(f"[codeguard] 内部错误已忽略(fail-open): {exc!r}", file=sys.stderr)
183188
sys.exit(0)

0 commit comments

Comments
 (0)