Skip to content

Commit 601ff64

Browse files
authored
release: v0.11.1(构建产物认知补全:单一事实源 + 四通道生效 + html NUL 管道) (#35)
需求:codeguard 得知道哪些是构建产物、不需要检测。实测两类永久红: target/**/apidocs/javadoc.sh(java 门禁自产、shell 门禁必红)与 target/site/jacoco/*.html(html 门禁必红);html 门禁旧 -exec 形态在产物 数百个时把整串换行路径塞进单参数(xargs: insufficient space)。 - 单一事实源:scope.FULL_SCAN_EXCLUDES 扩为 24 目录(补 out/.next/.nuxt/ .gradle/coverage/.terraform/.eggs/htmlcov/.turbo/.parcel-cache/三缓存/env), 新增 is_build_artifact() 谓词;gate_lib.GUARD_EXCLUDE_DIRS 改为派生 (本清单 + IDE 目录)——此前两份手抄清单已漂移:扫描面缺 14 个产物目录、 入库面缺 upstream - 注入器三形态全覆盖:-print0 锚(原样)、-exec 锚(旧 html 形态曾整族漏网)、 无 NUL 锚 → find <path> 后插入(c/objc/cuda);c/objc 的 -o 组补括号, 否则 -not -path 被 OR 优先级短路、排除形同虚设 - changed_files 过滤产物路径:force-add 进索引的 target 文件不进 delta 面 - PostToolUse should_skip 产物静默跳过:写 target/ 的生成物不跑 linter, 防止 AI"自动修复"生成物(改完下次构建又重写) - html 门禁改 NUL 全管道:print0 → xargs -0 grep -L → tr '\n' '\0' → xargs -0 htmlhint,消灭换行单参数溢出面(macOS grep -Z 是模糊匹配非 NUL 输出,实测不可用,故用 tr 转换) - spec 同步 language-gate-commands:ruff 单族 → 全门禁族 + 单源 + NUL 管道 - README×2 与 4 份 manifest → 0.11.1(v0.11.0 漏改 README 版本行,一并对齐) 验证:unittest 149/149(新增 tests/test_artifact_awareness.py 29 用例)、 run_all 141/0、validate_languages_json 11 规则、LANGUAGES.md 再生成零 diff
1 parent 14ac891 commit 601ff64

12 files changed

Lines changed: 269 additions & 37 deletions

File tree

‎.agents/plugins/marketplace.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@
99
"source": {
1010
"source": "url",
1111
"url": "https://github.com/partme-ai/partme-codeguard-plugin.git",
12-
"ref": "v0.11.0"
12+
"ref": "v0.11.1"
1313
},
1414
"policy": {
1515
"installation": "AVAILABLE",
1616
"authentication": "ON_USE"
1717
},
1818
"category": "Developer Tools",
19-
"version": "0.11.0",
19+
"version": "0.11.1",
2020
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
21-
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.11.0/assets/official-logo.png",
21+
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.11.1/assets/official-logo.png",
2222
"interface": {
2323
"displayName": "代码规范守卫",
2424
"shortDescription": "Make AI-written code pass lint on first try",
25-
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.11.0/assets/official-logo.png"
25+
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.11.1/assets/official-logo.png"
2626
}
2727
}
2828
]

‎.codex-plugin/plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codeguard",
3-
"version": "0.11.0+codex.20260922",
3+
"version": "0.11.1+codex.20260922",
44
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
55
"author": {
66
"name": "Full Stack Skills / PartMe.AI",

‎.zcode-plugin/plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"en": "CodeGuard",
66
"zh-CN": "代码规范检查"
77
},
8-
"version": "0.11.0",
8+
"version": "0.11.1",
99
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
1010
"description_i18n": {
1111
"en": "Cross-language code lint enforcement. PostToolUse hook auto-runs the language-specific linter on every AI-written file; failed lint blocks further writes when strict_mode is on. Ships ready-to-go .pre-commit-config.yaml templates for Java/Rust/TypeScript/Python.",

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ AI code that passes lint on first try
6767
|---|---|
6868
| Plugin ID | `partme-codeguard-plugin` |
6969
| Hosts | ZCode, Claude Code, Codex CLI, Kimi Code |
70-
| Current version | `0.10.1` |
70+
| Current version | `0.11.1` |
7171
| ZCode manifest | `.zcode-plugin/plugin.json` |
7272
| Codex manifest | `.codex-plugin/plugin.json` |
7373
| MCP server | Published: stdio server via the official SDK (`check_code_style` / `auto_fix` / `list_languages`); see Quick start |

‎README.zh-CN.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ AI 一次写出就过 lint 的代码
6767
|---|---|
6868
| 插件 ID | `partme-codeguard-plugin` |
6969
| 宿主 | ZCode、Claude Code、Codex CLI、Kimi Code |
70-
| 当前版本 | `0.10.1` |
70+
| 当前版本 | `0.11.1` |
7171
| ZCode manifest | `.zcode-plugin/plugin.json` |
7272
| Codex manifest | `.codex-plugin/plugin.json` |
7373
| MCP 服务 | 已发布:官方 SDK stdio 服务(`check_code_style` / `auto_fix` / `list_languages`);见快速开始 |

‎hooks/gate_lib.py‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,15 @@
3333
probe_toolchain,
3434
project_uses_linter,
3535
)
36-
from scope import changed_files, scope_cmd
36+
from scope import FULL_SCAN_EXCLUDES, changed_files, scope_cmd
3737

3838
# === git 提交内容安全检查:绝不该进版本库的文件 ===
39-
# 目录(路径任一段落匹配即违规):依赖/虚拟环境/构建产物/IDE/缓存
40-
GUARD_EXCLUDE_DIRS = {
41-
".venv", "venv", "env", "node_modules", "__pycache__", ".pytest_cache",
42-
".mypy_cache", ".ruff_cache", "target", "dist", "build", "out", ".next",
43-
".nuxt", ".gradle", "vendor", ".idea", ".vscode", "coverage", ".terraform",
44-
".tox", ".eggs", "htmlcov", ".turbo", ".parcel-cache",
45-
}
39+
# 目录 = 构建产物/依赖快照**单一事实源**(scope.FULL_SCAN_EXCLUDES)+ IDE 目录。
40+
# 从单一来源派生:清单只在 scope.py 改一处,"入库面"与"扫描面"永不漂移
41+
# (此前两份手抄清单已经漂移:扫描面缺 out/.next/coverage 等 14 个目录,
42+
# 入库面缺 upstream)。路径任一段落匹配即违规;vendor 的仓根级特例在
43+
# check_commit_safety 里(嵌套 scripts/vendor 是第一方源码树)。
44+
GUARD_EXCLUDE_DIRS = set(FULL_SCAN_EXCLUDES) | {".idea", ".vscode"}
4645
# 文件名模式(fnmatch,任意层级):密钥/凭据/本地环境/系统垃圾
4746
GUARD_EXCLUDE_FILES = [
4847
".env", ".env.*", "*.env", "*.pem", "*.key", "*.p12", "*.pfx", "*.jks",

‎hooks/post_tool_lint.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
project_uses_linter,
2828
)
2929
from gate_lib import codeguard_home, session_state_path
30-
from scope import scope_cmd # 状态目录 ~/.codeguard(可 CODEGUARD_HOME 覆盖)
30+
from scope import is_build_artifact, scope_cmd # 状态目录 ~/.codeguard(可 CODEGUARD_HOME 覆盖)
3131

3232
# 双副本去重:同一插件可能以多个 marketplace 副本安装(partme-ai/ 与
3333
# full-stack-plugins/ 各一份,钩子双份触发——实测),用户级固定路径跨副本共享
@@ -186,6 +186,12 @@ def extract_file_path(payload: dict) -> str:
186186
def should_skip(file_path: str, languages: list[str]) -> tuple[bool, str]:
187187
if not file_path:
188188
return True, ""
189+
# 构建产物静默跳过:写到 target/site、target/apidocs 的生成 HTML/sh 由
190+
# 构建流程负责,检查它们只会给出下次构建就被重写的假告警,AI 还可能
191+
# "自动修复"生成物(prettier 改完、构建一跑又变回去)。
192+
# 目录认知单源:scope.FULL_SCAN_EXCLUDES。
193+
if is_build_artifact(file_path):
194+
return True, ""
189195
lang = detect_language(file_path)
190196
if not lang:
191197
return True, ""

‎kimi.plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codeguard",
3-
"version": "0.11.0",
3+
"version": "0.11.1",
44
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
55
"author": {
66
"name": "Full Stack Skills / PartMe.AI"

‎openspec/specs/language-gate-commands/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ The functions `load_user_config`, `load_project_overrides`, and `get_overrides`
8888

8989
### Requirement: Gates in git repositories SHALL default to changed-file scope
9090

91-
git 仓库内的门禁 MUST 缺省只检查**本次操作面**涉及的文件,并按语言归属过滤;存量问题 MUST NOT 阻塞无关的新提交。操作面 MUST 由操作类型决定:**commit 面**(`git commit` 前)= staged + 未暂存 + 未跟踪;**push 面**(`git push` 前)= 提交面并集**未推送提交**(`up...HEAD` 三点差;无 upstream 时按 `origin/<当前分支>`→`origin/main`→`origin/master` 逐个尝试,均不可解析则不猜测、不崩溃)。面的判定 MUST 单源:命中判定与选面共用同一套扫描,直接命令与一层解释器间接不得分叉;同时命中 commit 与 push 时 MUST 取 push 面。提示词触发的软门禁 MUST 以同一套面语义选择(推送意图选 push 面)。项目可用 `codeguard.json` 的 `gate_scope`(`delta`/`repo`)显式覆盖;非 git 目录缺省为全量。全量模式 MUST 从 ruff 扫描中剔除依赖快照与构建产物目录(vendor/build/dist 等)。门禁结果缓存 MUST 按面隔离(mode 进缓存键),同一 HEAD 下两面不得互相污染。
91+
git 仓库内的门禁 MUST 缺省只检查**本次操作面**涉及的文件,并按语言归属过滤;存量问题 MUST NOT 阻塞无关的新提交。操作面 MUST 由操作类型决定:**commit 面**(`git commit` 前)= staged + 未暂存 + 未跟踪;**push 面**(`git push` 前)= 提交面并集**未推送提交**(`up...HEAD` 三点差;无 upstream 时按 `origin/<当前分支>`→`origin/main`→`origin/master` 逐个尝试,均不可解析则不猜测、不崩溃)。面的判定 MUST 单源:命中判定与选面共用同一套扫描,直接命令与一层解释器间接不得分叉;同时命中 commit 与 push 时 MUST 取 push 面。提示词触发的软门禁 MUST 以同一套面语义选择(推送意图选 push 面)。项目可用 `codeguard.json` 的 `gate_scope`(`delta`/`repo`)显式覆盖;非 git 目录缺省为全量。构建产物与依赖快照 MUST 有**单一事实源清单**(`scope.FULL_SCAN_EXCLUDES`),覆盖全量与 delta 两条路径的**所有门禁族**:ruff `--exclude`、find 型 gate 的 `-not -path` 注入(`-print0`/`-exec`/无 NUL 锚三形态全覆盖)、PostToolUse 对产物路径静默跳过、`changed_files` 过滤产物路径(force-add 的 target 文件不进 delta 面);「入库面」清单 MUST 由该单一事实源派生(+IDE 目录),两侧不得各自手抄。html 门禁 MUST 以 NUL 管道传递文件清单——`-exec … {} + | xargs -0` 的换行分隔会在产物数百个时把整串路径塞进单参数(`xargs: insufficient space` 实测)。门禁结果缓存 MUST 按面隔离(mode 进缓存键),同一 HEAD 下两面不得互相污染。
9292

9393
#### Scenario: A committed legacy issue is untouched by a clean change
9494

‎scripts/languages.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@
540540
"gate": [
541541
"bash",
542542
"-c",
543-
"find . -name '*.c' -o -name '*.h' | xargs -r clang-tidy --quiet"
543+
"find . \\( -name '*.c' -o -name '*.h' \\) | xargs -r clang-tidy --quiet"
544544
],
545545
"linter_config_files": [
546546
".clang-tidy",
@@ -603,7 +603,7 @@
603603
"gate": [
604604
"bash",
605605
"-c",
606-
"find . -name '*.m' -o -name '*.mm' | xargs -r clang-tidy --quiet"
606+
"find . \\( -name '*.m' -o -name '*.mm' \\) | xargs -r clang-tidy --quiet"
607607
],
608608
"linter_config_files": [
609609
".clang-tidy",
@@ -898,7 +898,7 @@
898898
"gate": [
899899
"bash",
900900
"-c",
901-
"find . \\( -name '*.html' -o -name '*.htm' \\) -type f -not -path '*/node_modules/*' -exec grep -L '<%' {} + | xargs -0 -r npx --no-install htmlhint"
901+
"find . \\( -name '*.html' -o -name '*.htm' \\) -type f -not -path '*/node_modules/*' -print0 | xargs -0 -r grep -L '<%' | tr '\\n' '\\0' | xargs -0 -r npx --no-install htmlhint"
902902
],
903903
"linter_config_files": [
904904
".htmlhintrc"

0 commit comments

Comments
 (0)